{
  "version": 3,
  "sources": ["../../../assets/node_modules/tailwindcss/lib/util/cloneDeep.js", "../../../assets/node_modules/tailwindcss/stubs/config.full.js", "../../../assets/node_modules/tailwindcss/lib/public/default-theme.js", "../../../assets/node_modules/tailwindcss/defaultTheme.js", "../../../assets/node_modules/toggle-selection/index.js", "../../../assets/node_modules/copy-to-clipboard/index.js", "../../../assets/node_modules/plyr/dist/plyr.js", "../../../assets/node_modules/plyr/dist/node_modules/rangetouch/dist/rangetouch.mjs", "../../../assets/node_modules/plyr/dist/src/js/utils/is.js", "../../../assets/node_modules/plyr/dist/src/js/utils/animation.js", "../../../assets/node_modules/plyr/dist/src/js/utils/browser.js", "../../../assets/node_modules/plyr/dist/src/js/utils/objects.js", "../../../assets/node_modules/plyr/dist/src/js/utils/elements.js", "../../../assets/node_modules/plyr/dist/src/js/support.js", "../../../assets/node_modules/plyr/dist/src/js/utils/events.js", "../../../assets/node_modules/plyr/dist/src/js/utils/promise.js", "../../../assets/node_modules/plyr/dist/src/js/utils/arrays.js", "../../../assets/node_modules/plyr/dist/src/js/utils/style.js", "../../../assets/node_modules/plyr/dist/src/js/html5.js", "../../../assets/node_modules/plyr/dist/src/js/utils/strings.js", "../../../assets/node_modules/plyr/dist/src/js/utils/i18n.js", "../../../assets/node_modules/plyr/dist/src/js/storage.js", "../../../assets/node_modules/plyr/dist/src/js/utils/fetch.js", "../../../assets/node_modules/plyr/dist/src/js/utils/load-sprite.js", "../../../assets/node_modules/plyr/dist/src/js/utils/time.js", "../../../assets/node_modules/plyr/dist/src/js/controls.js", "../../../assets/node_modules/plyr/dist/src/js/utils/urls.js", "../../../assets/node_modules/plyr/dist/src/js/captions.js", "../../../assets/node_modules/plyr/dist/src/js/config/defaults.js", "../../../assets/node_modules/plyr/dist/src/js/config/states.js", "../../../assets/node_modules/plyr/dist/src/js/config/types.js", "../../../assets/node_modules/plyr/dist/src/js/console.js", "../../../assets/node_modules/plyr/dist/src/js/fullscreen.js", "../../../assets/node_modules/plyr/dist/src/js/utils/load-image.js", "../../../assets/node_modules/plyr/dist/src/js/ui.js", "../../../assets/node_modules/plyr/dist/src/js/listeners.js", "../../../assets/node_modules/plyr/dist/node_modules/loadjs/dist/loadjs.umd.js", "../../../assets/node_modules/plyr/dist/src/js/utils/load-script.js", "../../../assets/node_modules/plyr/dist/src/js/plugins/vimeo.js", "../../../assets/node_modules/plyr/dist/src/js/plugins/youtube.js", "../../../assets/node_modules/plyr/dist/src/js/media.js", "../../../assets/node_modules/plyr/dist/src/js/plugins/ads.js", "../../../assets/node_modules/plyr/dist/src/js/plugins/preview-thumbnails.js", "../../../assets/node_modules/plyr/dist/src/js/source.js", "../../../assets/node_modules/plyr/dist/src/js/plyr.js", "../../../assets/node_modules/plyr/dist/src/js/utils/numbers.js", "../../../assets/node_modules/@alpinejs/persist/dist/module.esm.js", "../../../assets/node_modules/@splidejs/splide/dist/js/splide.esm.js", "../../../assets/node_modules/alpinejs/dist/module.esm.js", "../../../assets/node_modules/date-fns/esm/_lib/toInteger/index.js", "../../../assets/node_modules/date-fns/esm/_lib/requiredArgs/index.js", "../../../assets/node_modules/date-fns/esm/toDate/index.js", "../../../assets/node_modules/date-fns/esm/addDays/index.js", "../../../assets/node_modules/date-fns/esm/addMonths/index.js", "../../../assets/node_modules/date-fns/esm/add/index.js", "../../../assets/node_modules/date-fns/esm/addMilliseconds/index.js", "../../../assets/node_modules/date-fns/esm/_lib/getTimezoneOffsetInMilliseconds/index.js", "../../../assets/node_modules/date-fns/esm/startOfDay/index.js", "../../../assets/node_modules/date-fns/esm/differenceInCalendarDays/index.js", "../../../assets/node_modules/date-fns/esm/isValid/index.js", "../../../assets/node_modules/date-fns/esm/differenceInDays/index.js", "../../../assets/node_modules/date-fns/esm/differenceInMilliseconds/index.js", "../../../assets/node_modules/date-fns/esm/differenceInHours/index.js", "../../../assets/node_modules/date-fns/esm/differenceInMinutes/index.js", "../../../assets/node_modules/date-fns/esm/differenceInSeconds/index.js", "../../../assets/node_modules/date-fns/esm/locale/en-US/_lib/formatDistance/index.js", "../../../assets/node_modules/date-fns/esm/locale/_lib/buildFormatLongFn/index.js", "../../../assets/node_modules/date-fns/esm/locale/en-US/_lib/formatLong/index.js", "../../../assets/node_modules/date-fns/esm/locale/en-US/_lib/formatRelative/index.js", "../../../assets/node_modules/date-fns/esm/locale/_lib/buildLocalizeFn/index.js", "../../../assets/node_modules/date-fns/esm/locale/en-US/_lib/localize/index.js", "../../../assets/node_modules/date-fns/esm/locale/_lib/buildMatchPatternFn/index.js", "../../../assets/node_modules/date-fns/esm/locale/_lib/buildMatchFn/index.js", "../../../assets/node_modules/date-fns/esm/locale/en-US/_lib/match/index.js", "../../../assets/node_modules/date-fns/esm/locale/en-US/index.js", "../../../assets/node_modules/date-fns/esm/subMilliseconds/index.js", "../../../assets/node_modules/date-fns/esm/_lib/addLeadingZeros/index.js", "../../../assets/node_modules/date-fns/esm/_lib/format/lightFormatters/index.js", "../../../assets/node_modules/date-fns/esm/_lib/getUTCDayOfYear/index.js", "../../../assets/node_modules/date-fns/esm/_lib/startOfUTCISOWeek/index.js", "../../../assets/node_modules/date-fns/esm/_lib/getUTCISOWeekYear/index.js", "../../../assets/node_modules/date-fns/esm/_lib/startOfUTCISOWeekYear/index.js", "../../../assets/node_modules/date-fns/esm/_lib/getUTCISOWeek/index.js", "../../../assets/node_modules/date-fns/esm/_lib/startOfUTCWeek/index.js", "../../../assets/node_modules/date-fns/esm/_lib/getUTCWeekYear/index.js", "../../../assets/node_modules/date-fns/esm/_lib/startOfUTCWeekYear/index.js", "../../../assets/node_modules/date-fns/esm/_lib/getUTCWeek/index.js", "../../../assets/node_modules/date-fns/esm/_lib/format/formatters/index.js", "../../../assets/node_modules/date-fns/esm/_lib/format/longFormatters/index.js", "../../../assets/node_modules/date-fns/esm/_lib/protectedTokens/index.js", "../../../assets/node_modules/date-fns/esm/format/index.js", "../../../assets/node_modules/date-fns/esm/_lib/assign/index.js", "../../../assets/node_modules/date-fns/esm/_lib/cloneObject/index.js", "../../../assets/node_modules/date-fns/esm/parseISO/index.js", "../../../deps/phoenix/assets/js/phoenix/utils.js", "../../../deps/phoenix/assets/js/phoenix/constants.js", "../../../deps/phoenix/assets/js/phoenix/push.js", "../../../deps/phoenix/assets/js/phoenix/timer.js", "../../../deps/phoenix/assets/js/phoenix/channel.js", "../../../deps/phoenix/assets/js/phoenix/ajax.js", "../../../deps/phoenix/assets/js/phoenix/longpoll.js", "../../../deps/phoenix/assets/js/phoenix/presence.js", "../../../deps/phoenix/assets/js/phoenix/serializer.js", "../../../deps/phoenix/assets/js/phoenix/socket.js", "../../../deps/phoenix_html/priv/static/phoenix_html.js", "../../../deps/phoenix_live_view/assets/js/phoenix_live_view/constants.js", "../../../deps/phoenix_live_view/assets/js/phoenix_live_view/entry_uploader.js", "../../../deps/phoenix_live_view/assets/js/phoenix_live_view/utils.js", "../../../deps/phoenix_live_view/assets/js/phoenix_live_view/browser.js", "../../../deps/phoenix_live_view/assets/js/phoenix_live_view/dom.js", "../../../deps/phoenix_live_view/assets/js/phoenix_live_view/upload_entry.js", "../../../deps/phoenix_live_view/assets/js/phoenix_live_view/live_uploader.js", "../../../deps/phoenix_live_view/assets/js/phoenix_live_view/hooks.js", "../../../deps/phoenix_live_view/assets/js/phoenix_live_view/dom_post_morph_restorer.js", "../../../deps/phoenix_live_view/assets/node_modules/morphdom/dist/morphdom-esm.js", "../../../deps/phoenix_live_view/assets/js/phoenix_live_view/dom_patch.js", "../../../deps/phoenix_live_view/assets/js/phoenix_live_view/rendered.js", "../../../deps/phoenix_live_view/assets/js/phoenix_live_view/view_hook.js", "../../../deps/phoenix_live_view/assets/js/phoenix_live_view/js.js", "../../../deps/phoenix_live_view/assets/js/phoenix_live_view/view.js", "../../../deps/phoenix_live_view/assets/js/phoenix_live_view/live_socket.js", "../../../assets/node_modules/tailwind-merge/src/lib/tw-join.ts", "../../../assets/node_modules/tailwind-merge/dist/_virtual/_rollupPluginBabelHelpers.mjs", "../../../assets/node_modules/tailwind-merge/src/lib/class-utils.ts", "../../../assets/node_modules/tailwind-merge/src/lib/lru-cache.ts", "../../../assets/node_modules/tailwind-merge/src/lib/modifier-utils.ts", "../../../assets/node_modules/tailwind-merge/src/lib/config-utils.ts", "../../../assets/node_modules/tailwind-merge/src/lib/merge-classlist.ts", "../../../assets/node_modules/tailwind-merge/src/lib/create-tailwind-merge.ts", "../../../assets/node_modules/tailwind-merge/src/lib/from-theme.ts", "../../../assets/node_modules/tailwind-merge/src/lib/validators.ts", "../../../assets/node_modules/tailwind-merge/src/lib/default-config.ts", "../../../assets/node_modules/tailwind-merge/src/lib/tw-merge.ts", "../../../assets/js/app.js", "../../../assets/js/account.js", "../../../assets/js/common.js", "../../../assets/js/email_form.js", "../../../assets/js/onboarding.js", "../../../assets/node_modules/@vimeo/player/dist/player.es.js", "../../../assets/js/player.js", "../../../assets/node_modules/hls.js/dist/node_modules/url-toolkit/src/url-toolkit.js", "../../../assets/node_modules/hls.js/dist/src/polyfills/number.ts", "../../../assets/node_modules/hls.js/dist/src/events.ts", "../../../assets/node_modules/hls.js/dist/src/errors.ts", "../../../assets/node_modules/hls.js/dist/src/utils/logger.ts", "../../../assets/node_modules/hls.js/dist/src/utils/attr-list.ts", "../../../assets/node_modules/hls.js/dist/src/loader/date-range.ts", "../../../assets/node_modules/hls.js/dist/src/loader/load-stats.ts", "../../../assets/node_modules/hls.js/dist/src/loader/fragment.ts", "../../../assets/node_modules/hls.js/dist/src/loader/level-details.ts", "../../../assets/node_modules/hls.js/dist/src/utils/numeric-encoding-utils.ts", "../../../assets/node_modules/hls.js/dist/src/utils/keysystem-util.ts", "../../../assets/node_modules/hls.js/dist/src/utils/global.ts", "../../../assets/node_modules/hls.js/dist/src/utils/mediakeys-helper.ts", "../../../assets/node_modules/hls.js/dist/src/utils/typed-array.ts", "../../../assets/node_modules/hls.js/dist/src/demux/id3.ts", "../../../assets/node_modules/hls.js/dist/src/utils/hex.ts", "../../../assets/node_modules/hls.js/dist/src/utils/mp4-tools.ts", "../../../assets/node_modules/hls.js/dist/src/loader/level-key.ts", "../../../assets/node_modules/hls.js/dist/src/utils/variable-substitution.ts", "../../../assets/node_modules/hls.js/dist/src/utils/mediasource-helper.ts", "../../../assets/node_modules/hls.js/dist/src/utils/codecs.ts", "../../../assets/node_modules/hls.js/dist/src/loader/m3u8-parser.ts", "../../../assets/node_modules/hls.js/dist/src/types/loader.ts", "../../../assets/node_modules/hls.js/dist/src/loader/playlist-loader.ts", "../../../assets/node_modules/hls.js/dist/src/utils/texttrack-utils.ts", "../../../assets/node_modules/hls.js/dist/src/types/demuxer.ts", "../../../assets/node_modules/hls.js/dist/src/controller/id3-track-controller.ts", "../../../assets/node_modules/hls.js/dist/src/controller/latency-controller.ts", "../../../assets/node_modules/hls.js/dist/src/types/level.ts", "../../../assets/node_modules/hls.js/dist/src/utils/level-helper.ts", "../../../assets/node_modules/hls.js/dist/src/utils/error-helper.ts", "../../../assets/node_modules/hls.js/dist/src/utils/binary-search.ts", "../../../assets/node_modules/hls.js/dist/src/controller/fragment-finders.ts", "../../../assets/node_modules/hls.js/dist/src/controller/error-controller.ts", "../../../assets/node_modules/hls.js/dist/src/controller/base-playlist-controller.ts", "../../../assets/node_modules/hls.js/dist/src/utils/ewma.ts", "../../../assets/node_modules/hls.js/dist/src/utils/ewma-bandwidth-estimator.ts", "../../../assets/node_modules/hls.js/dist/src/utils/mediacapabilities-helper.ts", "../../../assets/node_modules/hls.js/dist/src/utils/hdr.ts", "../../../assets/node_modules/hls.js/dist/src/utils/rendition-helper.ts", "../../../assets/node_modules/hls.js/dist/src/controller/abr-controller.ts", "../../../assets/node_modules/hls.js/dist/src/task-loop.ts", "../../../assets/node_modules/hls.js/dist/src/controller/fragment-tracker.ts", "../../../assets/node_modules/hls.js/dist/src/utils/buffer-helper.ts", "../../../assets/node_modules/hls.js/dist/src/types/transmuxer.ts", "../../../assets/node_modules/hls.js/dist/src/utils/discontinuities.ts", "../../../assets/node_modules/hls.js/dist/src/loader/fragment-loader.ts", "../../../assets/node_modules/hls.js/dist/src/crypt/aes-crypto.ts", "../../../assets/node_modules/hls.js/dist/src/crypt/fast-aes-key.ts", "../../../assets/node_modules/hls.js/dist/src/crypt/aes-decryptor.ts", "../../../assets/node_modules/hls.js/dist/src/crypt/decrypter.ts", "../../../assets/node_modules/hls.js/dist/src/utils/time-ranges.ts", "../../../assets/node_modules/hls.js/dist/src/controller/base-stream-controller.ts", "../../../assets/node_modules/hls.js/dist/src/demux/chunk-cache.ts", "../../../assets/node_modules/hls.js/dist/src/demux/inject-worker.ts", "../../../assets/node_modules/hls.js/dist/src/demux/dummy-demuxed-track.ts", "../../../assets/node_modules/hls.js/dist/src/demux/audio/base-audio-demuxer.ts", "../../../assets/node_modules/hls.js/dist/src/demux/audio/adts.ts", "../../../assets/node_modules/hls.js/dist/src/demux/audio/mpegaudio.ts", "../../../assets/node_modules/hls.js/dist/src/demux/audio/aacdemuxer.ts", "../../../assets/node_modules/hls.js/dist/src/demux/mp4demuxer.ts", "../../../assets/node_modules/hls.js/dist/src/demux/audio/dolby.ts", "../../../assets/node_modules/hls.js/dist/src/demux/audio/ac3-demuxer.ts", "../../../assets/node_modules/hls.js/dist/src/demux/video/base-video-parser.ts", "../../../assets/node_modules/hls.js/dist/src/demux/video/exp-golomb.ts", "../../../assets/node_modules/hls.js/dist/src/demux/video/avc-video-parser.ts", "../../../assets/node_modules/hls.js/dist/src/demux/sample-aes.ts", "../../../assets/node_modules/hls.js/dist/src/demux/tsdemuxer.ts", "../../../assets/node_modules/hls.js/dist/src/demux/audio/mp3demuxer.ts", "../../../assets/node_modules/hls.js/dist/src/remux/aac-helper.ts", "../../../assets/node_modules/hls.js/dist/src/remux/mp4-generator.ts", "../../../assets/node_modules/hls.js/dist/src/utils/timescale-conversion.ts", "../../../assets/node_modules/hls.js/dist/src/remux/mp4-remuxer.ts", "../../../assets/node_modules/hls.js/dist/src/remux/passthrough-remuxer.ts", "../../../assets/node_modules/hls.js/dist/src/demux/transmuxer.ts", "../../../assets/node_modules/hls.js/dist/node_modules/eventemitter3/index.js", "../../../assets/node_modules/hls.js/dist/src/demux/transmuxer-interface.ts", "../../../assets/node_modules/hls.js/dist/src/utils/media-option-attributes.ts", "../../../assets/node_modules/hls.js/dist/src/controller/audio-stream-controller.ts", "../../../assets/node_modules/hls.js/dist/src/controller/audio-track-controller.ts", "../../../assets/node_modules/hls.js/dist/src/controller/subtitle-stream-controller.ts", "../../../assets/node_modules/hls.js/dist/src/controller/subtitle-track-controller.ts", "../../../assets/node_modules/hls.js/dist/src/controller/buffer-operation-queue.ts", "../../../assets/node_modules/hls.js/dist/src/controller/buffer-controller.ts", "../../../assets/node_modules/hls.js/dist/src/utils/cea-608-parser.ts", "../../../assets/node_modules/hls.js/dist/src/utils/output-filter.ts", "../../../assets/node_modules/hls.js/dist/src/utils/vttcue.ts", "../../../assets/node_modules/hls.js/dist/src/utils/vttparser.ts", "../../../assets/node_modules/hls.js/dist/src/utils/webvtt-parser.ts", "../../../assets/node_modules/hls.js/dist/src/utils/imsc1-ttml-parser.ts", "../../../assets/node_modules/hls.js/dist/src/controller/timeline-controller.ts", "../../../assets/node_modules/hls.js/dist/src/controller/cap-level-controller.ts", "../../../assets/node_modules/hls.js/dist/src/controller/fps-controller.ts", "../../../assets/node_modules/hls.js/dist/src/controller/eme-controller.ts", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/cta/CmObjectType.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/cta/CmStreamingFormat.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/cmcd/CmcdHeaderField.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/cmcd/CmcdHeaderMap.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/SfItem.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/SfToken.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/utils/DICT.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/utils/throwError.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/utils/BARE_ITEM.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/utils/BOOLEAN.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/utils/BYTES.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/utils/DECIMAL.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/utils/INTEGER.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/utils/isInvalidInt.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/utils/STRING_REGEX.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/utils/TOKEN.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/utils/KEY.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/serialize/serializeError.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/serialize/serializeBoolean.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/utils/base64encode.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/serialize/serializeByteSequence.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/serialize/serializeInteger.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/serialize/serializeDate.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/utils/roundToEven.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/serialize/serializeDecimal.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/utils/STRING.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/serialize/serializeString.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/cta/utils/symbolToStr.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/serialize/serializeToken.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/serialize/serializeBareItem.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/serialize/serializeKey.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/serialize/serializeParams.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/serialize/serializeItem.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/serialize/serializeInnerList.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/serialize/serializeDict.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/structuredfield/encodeSfDict.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/cta/utils/isTokenField.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/cta/utils/isValid.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/utils/urlToRelativePath.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/utils/uuid.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/cmcd/CmcdFormatters.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/cmcd/utils/processCmcd.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/cmcd/encodeCmcd.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/cmcd/toCmcdHeaders.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/cmcd/appendCmcdHeaders.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/cmcd/CMCD_PARAM.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/cmcd/toCmcdQuery.js", "../../../assets/node_modules/hls.js/dist/node_modules/@svta/common-media-library/dist/cmcd/appendCmcdQuery.js", "../../../assets/node_modules/hls.js/dist/src/controller/cmcd-controller.ts", "../../../assets/node_modules/hls.js/dist/src/controller/content-steering-controller.ts", "../../../assets/node_modules/hls.js/dist/src/utils/xhr-loader.ts", "../../../assets/node_modules/hls.js/dist/src/utils/fetch-loader.ts", "../../../assets/node_modules/hls.js/dist/src/utils/cues.ts", "../../../assets/node_modules/hls.js/dist/src/config.ts", "../../../assets/node_modules/hls.js/dist/src/controller/level-controller.ts", "../../../assets/node_modules/hls.js/dist/src/loader/key-loader.ts", "../../../assets/node_modules/hls.js/dist/src/is-supported.ts", "../../../assets/node_modules/hls.js/dist/src/controller/gap-controller.ts", "../../../assets/node_modules/hls.js/dist/src/controller/stream-controller.ts", "../../../assets/node_modules/hls.js/dist/src/hls.ts", "../../../assets/js/plyr.js", "../../../assets/js/project.js", "../../../assets/js/quest_handler.js", "../../../assets/js/sharing.js", "../../../assets/js/sortable_list.js", "../../../assets/node_modules/ssr-window/ssr-window.esm.js", "../../../assets/node_modules/dom7/dom7.esm.js", "../../../assets/node_modules/swiper/shared/dom.js", "../../../assets/node_modules/swiper/shared/utils.js", "../../../assets/node_modules/swiper/shared/get-support.js", "../../../assets/node_modules/swiper/shared/get-device.js", "../../../assets/node_modules/swiper/shared/get-browser.js", "../../../assets/node_modules/swiper/core/modules/resize/resize.js", "../../../assets/node_modules/swiper/core/modules/observer/observer.js", "../../../assets/node_modules/swiper/core/events-emitter.js", "../../../assets/node_modules/swiper/core/update/updateSize.js", "../../../assets/node_modules/swiper/core/update/updateSlides.js", "../../../assets/node_modules/swiper/core/update/updateAutoHeight.js", "../../../assets/node_modules/swiper/core/update/updateSlidesOffset.js", "../../../assets/node_modules/swiper/core/update/updateSlidesProgress.js", "../../../assets/node_modules/swiper/core/update/updateProgress.js", "../../../assets/node_modules/swiper/core/update/updateSlidesClasses.js", "../../../assets/node_modules/swiper/core/update/updateActiveIndex.js", "../../../assets/node_modules/swiper/core/update/updateClickedSlide.js", "../../../assets/node_modules/swiper/core/update/index.js", "../../../assets/node_modules/swiper/core/translate/getTranslate.js", "../../../assets/node_modules/swiper/core/translate/setTranslate.js", "../../../assets/node_modules/swiper/core/translate/minTranslate.js", "../../../assets/node_modules/swiper/core/translate/maxTranslate.js", "../../../assets/node_modules/swiper/core/translate/translateTo.js", "../../../assets/node_modules/swiper/core/translate/index.js", "../../../assets/node_modules/swiper/core/transition/setTransition.js", "../../../assets/node_modules/swiper/core/transition/transitionEmit.js", "../../../assets/node_modules/swiper/core/transition/transitionStart.js", "../../../assets/node_modules/swiper/core/transition/transitionEnd.js", "../../../assets/node_modules/swiper/core/transition/index.js", "../../../assets/node_modules/swiper/core/slide/slideTo.js", "../../../assets/node_modules/swiper/core/slide/slideToLoop.js", "../../../assets/node_modules/swiper/core/slide/slideNext.js", "../../../assets/node_modules/swiper/core/slide/slidePrev.js", "../../../assets/node_modules/swiper/core/slide/slideReset.js", "../../../assets/node_modules/swiper/core/slide/slideToClosest.js", "../../../assets/node_modules/swiper/core/slide/slideToClickedSlide.js", "../../../assets/node_modules/swiper/core/slide/index.js", "../../../assets/node_modules/swiper/core/loop/loopCreate.js", "../../../assets/node_modules/swiper/core/loop/loopFix.js", "../../../assets/node_modules/swiper/core/loop/loopDestroy.js", "../../../assets/node_modules/swiper/core/loop/index.js", "../../../assets/node_modules/swiper/core/grab-cursor/setGrabCursor.js", "../../../assets/node_modules/swiper/core/grab-cursor/unsetGrabCursor.js", "../../../assets/node_modules/swiper/core/grab-cursor/index.js", "../../../assets/node_modules/swiper/core/events/onTouchStart.js", "../../../assets/node_modules/swiper/core/events/onTouchMove.js", "../../../assets/node_modules/swiper/core/events/onTouchEnd.js", "../../../assets/node_modules/swiper/core/events/onResize.js", "../../../assets/node_modules/swiper/core/events/onClick.js", "../../../assets/node_modules/swiper/core/events/onScroll.js", "../../../assets/node_modules/swiper/core/events/index.js", "../../../assets/node_modules/swiper/core/breakpoints/setBreakpoint.js", "../../../assets/node_modules/swiper/core/breakpoints/getBreakpoint.js", "../../../assets/node_modules/swiper/core/breakpoints/index.js", "../../../assets/node_modules/swiper/core/classes/addClasses.js", "../../../assets/node_modules/swiper/core/classes/removeClasses.js", "../../../assets/node_modules/swiper/core/classes/index.js", "../../../assets/node_modules/swiper/core/images/loadImage.js", "../../../assets/node_modules/swiper/core/images/preloadImages.js", "../../../assets/node_modules/swiper/core/images/index.js", "../../../assets/node_modules/swiper/core/check-overflow/index.js", "../../../assets/node_modules/swiper/core/defaults.js", "../../../assets/node_modules/swiper/core/moduleExtendParams.js", "../../../assets/node_modules/swiper/core/core.js", "../../../assets/js/swiper.js", "../../../assets/node_modules/date-fns-tz/esm/_lib/tzTokenizeDate/index.js", "../../../assets/node_modules/date-fns-tz/esm/_lib/tzParseTimezone/index.js", "../../../assets/node_modules/date-fns-tz/esm/toDate/index.js", "../../../assets/node_modules/date-fns-tz/esm/zonedTimeToUtc/index.js", "../../../assets/node_modules/canvas-confetti/dist/confetti.module.mjs", "../../../assets/js/util.js", "../../../assets/js/hooks/flip_list.js", "../../../assets/js/hooks/credits_sync.js", "../../../assets/js/hooks/rank_preview.js", "../../../assets/js/hooks/px_countdown.js", "../../../assets/node_modules/qrcode-generator/dist/qrcode.mjs", "../../../assets/js/hooks/popcorn.js", "../../../assets/js/landing/fill.js", "../../../assets/js/idle_sleep.js", "../../../assets/js/shows_j.js", "../../../assets/js/ad_events.js", "../../../assets/js/clicky_goals.js", "../../../assets/js/loot_sheet.js", "../../../assets/js/join_sheet.js", "../../../assets/js/project_x.js", "../../../assets/node_modules/media-chrome/dist/constants.js", "../../../assets/node_modules/media-chrome/dist/labels/labels.js", "../../../assets/node_modules/media-chrome/dist/utils/utils.js", "../../../assets/node_modules/media-chrome/dist/utils/time.js", "../../../assets/node_modules/media-chrome/dist/utils/server-safe-globals.js", "../../../assets/node_modules/media-chrome/dist/utils/resize-observer.js", "../../../assets/node_modules/media-chrome/dist/utils/element-utils.js", "../../../assets/node_modules/media-chrome/dist/media-gesture-receiver.js", "../../../assets/node_modules/media-chrome/dist/media-container.js", "../../../assets/node_modules/media-chrome/dist/utils/attribute-token-list.js", "../../../assets/node_modules/media-chrome/dist/utils/captions.js", "../../../assets/node_modules/media-chrome/dist/utils/fullscreen-api.js", "../../../assets/node_modules/media-chrome/dist/utils/platform-tests.js", "../../../assets/node_modules/media-chrome/dist/media-store/util.js", "../../../assets/node_modules/media-chrome/dist/media-store/state-mediator.js", "../../../assets/node_modules/media-chrome/dist/media-store/request-map.js", "../../../assets/node_modules/media-chrome/dist/media-store/media-store.js", "../../../assets/node_modules/media-chrome/dist/media-controller.js", "../../../assets/node_modules/media-chrome/dist/media-chrome-button.js", "../../../assets/node_modules/media-chrome/dist/media-airplay-button.js", "../../../assets/node_modules/media-chrome/dist/media-captions-button.js", "../../../assets/node_modules/media-chrome/dist/media-cast-button.js", "../../../assets/node_modules/media-chrome/dist/media-chrome-dialog.js", "../../../assets/node_modules/media-chrome/dist/media-chrome-range.js", "../../../assets/node_modules/media-chrome/dist/media-control-bar.js", "../../../assets/node_modules/media-chrome/dist/media-text-display.js", "../../../assets/node_modules/media-chrome/dist/media-duration-display.js", "../../../assets/node_modules/media-chrome/dist/media-fullscreen-button.js", "../../../assets/node_modules/media-chrome/dist/media-live-button.js", "../../../assets/node_modules/media-chrome/dist/media-loading-indicator.js", "../../../assets/node_modules/media-chrome/dist/media-mute-button.js", "../../../assets/node_modules/media-chrome/dist/media-pip-button.js", "../../../assets/node_modules/media-chrome/dist/media-playback-rate-button.js", "../../../assets/node_modules/media-chrome/dist/media-play-button.js", "../../../assets/node_modules/media-chrome/dist/media-poster-image.js", "../../../assets/node_modules/media-chrome/dist/media-preview-chapter-display.js", "../../../assets/node_modules/media-chrome/dist/media-preview-thumbnail.js", "../../../assets/node_modules/media-chrome/dist/media-preview-time-display.js", "../../../assets/node_modules/media-chrome/dist/media-seek-backward-button.js", "../../../assets/node_modules/media-chrome/dist/media-seek-forward-button.js", "../../../assets/node_modules/media-chrome/dist/media-time-display.js", "../../../assets/node_modules/media-chrome/dist/utils/range-animation.js", "../../../assets/node_modules/media-chrome/dist/media-time-range.js", "../../../assets/node_modules/media-chrome/dist/media-tooltip.js", "../../../assets/node_modules/media-chrome/dist/media-volume-range.js", "../../../assets/node_modules/mux-embed/dist/mux.mjs", "../../../assets/node_modules/@mux/playback-core/src/index.ts", "../../../assets/node_modules/@mux/playback-core/src/hls.ts", "../../../assets/node_modules/@mux/playback-core/src/errors.ts", "../../../assets/node_modules/@mux/playback-core/src/types.ts", "../../../assets/node_modules/@mux/playback-core/lang/en.json", "../../../assets/node_modules/@mux/playback-core/src/util.ts", "../../../assets/node_modules/@mux/playback-core/src/autoplay.ts", "../../../assets/node_modules/@mux/playback-core/src/preload.ts", "../../../assets/node_modules/@mux/playback-core/src/media-tracks.ts", "../../../assets/node_modules/@mux/playback-core/src/text-tracks.ts", "../../../assets/node_modules/@mux/playback-core/src/pdt.ts", "../../../assets/node_modules/@mux/playback-core/src/request-errors.ts", "../../../assets/node_modules/@mux/mux-video/src/polyfills/index.ts", "../../../assets/node_modules/@mux/mux-video/src/index.ts", "../../../assets/node_modules/@mux/mux-video/src/env.ts", "../../../assets/node_modules/node_modules/custom-media-element/custom-media-element.js", "../../../assets/node_modules/node_modules/castable-video/castable-utils.js", "../../../assets/node_modules/node_modules/castable-video/castable-remote-playback.js", "../../../assets/node_modules/node_modules/castable-video/castable-mixin.js", "../../../assets/node_modules/node_modules/media-tracks/dist/track-event.js", "../../../assets/node_modules/node_modules/media-tracks/dist/utils.js", "../../../assets/node_modules/node_modules/media-tracks/dist/video-track-list.js", "../../../assets/node_modules/node_modules/media-tracks/dist/rendition-event.js", "../../../assets/node_modules/node_modules/media-tracks/dist/video-rendition-list.js", "../../../assets/node_modules/node_modules/media-tracks/dist/video-rendition.js", "../../../assets/node_modules/node_modules/media-tracks/dist/video-track.js", "../../../assets/node_modules/node_modules/media-tracks/dist/audio-rendition-list.js", "../../../assets/node_modules/node_modules/media-tracks/dist/audio-rendition.js", "../../../assets/node_modules/node_modules/media-tracks/dist/audio-track-list.js", "../../../assets/node_modules/node_modules/media-tracks/dist/audio-track.js", "../../../assets/node_modules/node_modules/media-tracks/dist/mixin.js", "../../../assets/node_modules/media-chrome/dist/utils/template-parts.js", "../../../assets/node_modules/media-chrome/dist/utils/template-processor.js", "../../../assets/node_modules/media-chrome/dist/media-theme-element.js", "../../../assets/node_modules/media-chrome/dist/utils/anchor-utils.js", "../../../assets/node_modules/media-chrome/dist/utils/events.js", "../../../assets/node_modules/media-chrome/dist/menu/media-chrome-menu.js", "../../../assets/node_modules/media-chrome/dist/menu/media-chrome-menu-item.js", "../../../assets/node_modules/media-chrome/dist/menu/media-settings-menu.js", "../../../assets/node_modules/media-chrome/dist/menu/media-settings-menu-item.js", "../../../assets/node_modules/media-chrome/dist/menu/media-chrome-menu-button.js", "../../../assets/node_modules/media-chrome/dist/menu/media-settings-menu-button.js", "../../../assets/node_modules/media-chrome/dist/menu/media-audio-track-menu.js", "../../../assets/node_modules/media-chrome/dist/menu/media-audio-track-menu-button.js", "../../../assets/node_modules/media-chrome/dist/menu/media-captions-menu.js", "../../../assets/node_modules/media-chrome/dist/menu/media-captions-menu-button.js", "../../../assets/node_modules/media-chrome/dist/menu/media-playback-rate-menu.js", "../../../assets/node_modules/media-chrome/dist/menu/media-playback-rate-menu-button.js", "../../../assets/node_modules/media-chrome/dist/menu/media-rendition-menu.js", "../../../assets/node_modules/media-chrome/dist/menu/media-rendition-menu-button.js", "../../../assets/node_modules/@mux/mux-player/dist/index.mjs"],
  "sourcesContent": ["\"use strict\";\nObject.defineProperty(exports, \"__esModule\", {\n    value: true\n});\nObject.defineProperty(exports, \"cloneDeep\", {\n    enumerable: true,\n    get: function() {\n        return cloneDeep;\n    }\n});\nfunction cloneDeep(value) {\n    if (Array.isArray(value)) {\n        return value.map((child)=>cloneDeep(child));\n    }\n    if (typeof value === \"object\" && value !== null) {\n        return Object.fromEntries(Object.entries(value).map(([k, v])=>[\n                k,\n                cloneDeep(v)\n            ]));\n    }\n    return value;\n}\n", "module.exports = {\n  content: [],\n  presets: [],\n  darkMode: 'media', // or 'class'\n  theme: {\n    accentColor: ({ theme }) => ({\n      ...theme('colors'),\n      auto: 'auto',\n    }),\n    animation: {\n      none: 'none',\n      spin: 'spin 1s linear infinite',\n      ping: 'ping 1s cubic-bezier(0, 0, 0.2, 1) infinite',\n      pulse: 'pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite',\n      bounce: 'bounce 1s infinite',\n    },\n    aria: {\n      busy: 'busy=\"true\"',\n      checked: 'checked=\"true\"',\n      disabled: 'disabled=\"true\"',\n      expanded: 'expanded=\"true\"',\n      hidden: 'hidden=\"true\"',\n      pressed: 'pressed=\"true\"',\n      readonly: 'readonly=\"true\"',\n      required: 'required=\"true\"',\n      selected: 'selected=\"true\"',\n    },\n    aspectRatio: {\n      auto: 'auto',\n      square: '1 / 1',\n      video: '16 / 9',\n    },\n    backdropBlur: ({ theme }) => theme('blur'),\n    backdropBrightness: ({ theme }) => theme('brightness'),\n    backdropContrast: ({ theme }) => theme('contrast'),\n    backdropGrayscale: ({ theme }) => theme('grayscale'),\n    backdropHueRotate: ({ theme }) => theme('hueRotate'),\n    backdropInvert: ({ theme }) => theme('invert'),\n    backdropOpacity: ({ theme }) => theme('opacity'),\n    backdropSaturate: ({ theme }) => theme('saturate'),\n    backdropSepia: ({ theme }) => theme('sepia'),\n    backgroundColor: ({ theme }) => theme('colors'),\n    backgroundImage: {\n      none: 'none',\n      'gradient-to-t': 'linear-gradient(to top, var(--tw-gradient-stops))',\n      'gradient-to-tr': 'linear-gradient(to top right, var(--tw-gradient-stops))',\n      'gradient-to-r': 'linear-gradient(to right, var(--tw-gradient-stops))',\n      'gradient-to-br': 'linear-gradient(to bottom right, var(--tw-gradient-stops))',\n      'gradient-to-b': 'linear-gradient(to bottom, var(--tw-gradient-stops))',\n      'gradient-to-bl': 'linear-gradient(to bottom left, var(--tw-gradient-stops))',\n      'gradient-to-l': 'linear-gradient(to left, var(--tw-gradient-stops))',\n      'gradient-to-tl': 'linear-gradient(to top left, var(--tw-gradient-stops))',\n    },\n    backgroundOpacity: ({ theme }) => theme('opacity'),\n    backgroundPosition: {\n      bottom: 'bottom',\n      center: 'center',\n      left: 'left',\n      'left-bottom': 'left bottom',\n      'left-top': 'left top',\n      right: 'right',\n      'right-bottom': 'right bottom',\n      'right-top': 'right top',\n      top: 'top',\n    },\n    backgroundSize: {\n      auto: 'auto',\n      cover: 'cover',\n      contain: 'contain',\n    },\n    blur: {\n      0: '0',\n      none: '',\n      sm: '4px',\n      DEFAULT: '8px',\n      md: '12px',\n      lg: '16px',\n      xl: '24px',\n      '2xl': '40px',\n      '3xl': '64px',\n    },\n    borderColor: ({ theme }) => ({\n      ...theme('colors'),\n      DEFAULT: theme('colors.gray.200', 'currentColor'),\n    }),\n    borderOpacity: ({ theme }) => theme('opacity'),\n    borderRadius: {\n      none: '0px',\n      sm: '0.125rem',\n      DEFAULT: '0.25rem',\n      md: '0.375rem',\n      lg: '0.5rem',\n      xl: '0.75rem',\n      '2xl': '1rem',\n      '3xl': '1.5rem',\n      full: '9999px',\n    },\n    borderSpacing: ({ theme }) => ({\n      ...theme('spacing'),\n    }),\n    borderWidth: {\n      DEFAULT: '1px',\n      0: '0px',\n      2: '2px',\n      4: '4px',\n      8: '8px',\n    },\n    boxShadow: {\n      sm: '0 1px 2px 0 rgb(0 0 0 / 0.05)',\n      DEFAULT: '0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)',\n      md: '0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)',\n      lg: '0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)',\n      xl: '0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)',\n      '2xl': '0 25px 50px -12px rgb(0 0 0 / 0.25)',\n      inner: 'inset 0 2px 4px 0 rgb(0 0 0 / 0.05)',\n      none: 'none',\n    },\n    boxShadowColor: ({ theme }) => theme('colors'),\n    brightness: {\n      0: '0',\n      50: '.5',\n      75: '.75',\n      90: '.9',\n      95: '.95',\n      100: '1',\n      105: '1.05',\n      110: '1.1',\n      125: '1.25',\n      150: '1.5',\n      200: '2',\n    },\n    caretColor: ({ theme }) => theme('colors'),\n    colors: ({ colors }) => ({\n      inherit: colors.inherit,\n      current: colors.current,\n      transparent: colors.transparent,\n      black: colors.black,\n      white: colors.white,\n      slate: colors.slate,\n      gray: colors.gray,\n      zinc: colors.zinc,\n      neutral: colors.neutral,\n      stone: colors.stone,\n      red: colors.red,\n      orange: colors.orange,\n      amber: colors.amber,\n      yellow: colors.yellow,\n      lime: colors.lime,\n      green: colors.green,\n      emerald: colors.emerald,\n      teal: colors.teal,\n      cyan: colors.cyan,\n      sky: colors.sky,\n      blue: colors.blue,\n      indigo: colors.indigo,\n      violet: colors.violet,\n      purple: colors.purple,\n      fuchsia: colors.fuchsia,\n      pink: colors.pink,\n      rose: colors.rose,\n    }),\n    columns: {\n      auto: 'auto',\n      1: '1',\n      2: '2',\n      3: '3',\n      4: '4',\n      5: '5',\n      6: '6',\n      7: '7',\n      8: '8',\n      9: '9',\n      10: '10',\n      11: '11',\n      12: '12',\n      '3xs': '16rem',\n      '2xs': '18rem',\n      xs: '20rem',\n      sm: '24rem',\n      md: '28rem',\n      lg: '32rem',\n      xl: '36rem',\n      '2xl': '42rem',\n      '3xl': '48rem',\n      '4xl': '56rem',\n      '5xl': '64rem',\n      '6xl': '72rem',\n      '7xl': '80rem',\n    },\n    container: {},\n    content: {\n      none: 'none',\n    },\n    contrast: {\n      0: '0',\n      50: '.5',\n      75: '.75',\n      100: '1',\n      125: '1.25',\n      150: '1.5',\n      200: '2',\n    },\n    cursor: {\n      auto: 'auto',\n      default: 'default',\n      pointer: 'pointer',\n      wait: 'wait',\n      text: 'text',\n      move: 'move',\n      help: 'help',\n      'not-allowed': 'not-allowed',\n      none: 'none',\n      'context-menu': 'context-menu',\n      progress: 'progress',\n      cell: 'cell',\n      crosshair: 'crosshair',\n      'vertical-text': 'vertical-text',\n      alias: 'alias',\n      copy: 'copy',\n      'no-drop': 'no-drop',\n      grab: 'grab',\n      grabbing: 'grabbing',\n      'all-scroll': 'all-scroll',\n      'col-resize': 'col-resize',\n      'row-resize': 'row-resize',\n      'n-resize': 'n-resize',\n      'e-resize': 'e-resize',\n      's-resize': 's-resize',\n      'w-resize': 'w-resize',\n      'ne-resize': 'ne-resize',\n      'nw-resize': 'nw-resize',\n      'se-resize': 'se-resize',\n      'sw-resize': 'sw-resize',\n      'ew-resize': 'ew-resize',\n      'ns-resize': 'ns-resize',\n      'nesw-resize': 'nesw-resize',\n      'nwse-resize': 'nwse-resize',\n      'zoom-in': 'zoom-in',\n      'zoom-out': 'zoom-out',\n    },\n    divideColor: ({ theme }) => theme('borderColor'),\n    divideOpacity: ({ theme }) => theme('borderOpacity'),\n    divideWidth: ({ theme }) => theme('borderWidth'),\n    dropShadow: {\n      sm: '0 1px 1px rgb(0 0 0 / 0.05)',\n      DEFAULT: ['0 1px 2px rgb(0 0 0 / 0.1)', '0 1px 1px rgb(0 0 0 / 0.06)'],\n      md: ['0 4px 3px rgb(0 0 0 / 0.07)', '0 2px 2px rgb(0 0 0 / 0.06)'],\n      lg: ['0 10px 8px rgb(0 0 0 / 0.04)', '0 4px 3px rgb(0 0 0 / 0.1)'],\n      xl: ['0 20px 13px rgb(0 0 0 / 0.03)', '0 8px 5px rgb(0 0 0 / 0.08)'],\n      '2xl': '0 25px 25px rgb(0 0 0 / 0.15)',\n      none: '0 0 #0000',\n    },\n    fill: ({ theme }) => ({\n      none: 'none',\n      ...theme('colors'),\n    }),\n    flex: {\n      1: '1 1 0%',\n      auto: '1 1 auto',\n      initial: '0 1 auto',\n      none: 'none',\n    },\n    flexBasis: ({ theme }) => ({\n      auto: 'auto',\n      ...theme('spacing'),\n      '1/2': '50%',\n      '1/3': '33.333333%',\n      '2/3': '66.666667%',\n      '1/4': '25%',\n      '2/4': '50%',\n      '3/4': '75%',\n      '1/5': '20%',\n      '2/5': '40%',\n      '3/5': '60%',\n      '4/5': '80%',\n      '1/6': '16.666667%',\n      '2/6': '33.333333%',\n      '3/6': '50%',\n      '4/6': '66.666667%',\n      '5/6': '83.333333%',\n      '1/12': '8.333333%',\n      '2/12': '16.666667%',\n      '3/12': '25%',\n      '4/12': '33.333333%',\n      '5/12': '41.666667%',\n      '6/12': '50%',\n      '7/12': '58.333333%',\n      '8/12': '66.666667%',\n      '9/12': '75%',\n      '10/12': '83.333333%',\n      '11/12': '91.666667%',\n      full: '100%',\n    }),\n    flexGrow: {\n      0: '0',\n      DEFAULT: '1',\n    },\n    flexShrink: {\n      0: '0',\n      DEFAULT: '1',\n    },\n    fontFamily: {\n      sans: [\n        'ui-sans-serif',\n        'system-ui',\n        'sans-serif',\n        '\"Apple Color Emoji\"',\n        '\"Segoe UI Emoji\"',\n        '\"Segoe UI Symbol\"',\n        '\"Noto Color Emoji\"',\n      ],\n      serif: ['ui-serif', 'Georgia', 'Cambria', '\"Times New Roman\"', 'Times', 'serif'],\n      mono: [\n        'ui-monospace',\n        'SFMono-Regular',\n        'Menlo',\n        'Monaco',\n        'Consolas',\n        '\"Liberation Mono\"',\n        '\"Courier New\"',\n        'monospace',\n      ],\n    },\n    fontSize: {\n      xs: ['0.75rem', { lineHeight: '1rem' }],\n      sm: ['0.875rem', { lineHeight: '1.25rem' }],\n      base: ['1rem', { lineHeight: '1.5rem' }],\n      lg: ['1.125rem', { lineHeight: '1.75rem' }],\n      xl: ['1.25rem', { lineHeight: '1.75rem' }],\n      '2xl': ['1.5rem', { lineHeight: '2rem' }],\n      '3xl': ['1.875rem', { lineHeight: '2.25rem' }],\n      '4xl': ['2.25rem', { lineHeight: '2.5rem' }],\n      '5xl': ['3rem', { lineHeight: '1' }],\n      '6xl': ['3.75rem', { lineHeight: '1' }],\n      '7xl': ['4.5rem', { lineHeight: '1' }],\n      '8xl': ['6rem', { lineHeight: '1' }],\n      '9xl': ['8rem', { lineHeight: '1' }],\n    },\n    fontWeight: {\n      thin: '100',\n      extralight: '200',\n      light: '300',\n      normal: '400',\n      medium: '500',\n      semibold: '600',\n      bold: '700',\n      extrabold: '800',\n      black: '900',\n    },\n    gap: ({ theme }) => theme('spacing'),\n    gradientColorStops: ({ theme }) => theme('colors'),\n    gradientColorStopPositions: {\n      '0%': '0%',\n      '5%': '5%',\n      '10%': '10%',\n      '15%': '15%',\n      '20%': '20%',\n      '25%': '25%',\n      '30%': '30%',\n      '35%': '35%',\n      '40%': '40%',\n      '45%': '45%',\n      '50%': '50%',\n      '55%': '55%',\n      '60%': '60%',\n      '65%': '65%',\n      '70%': '70%',\n      '75%': '75%',\n      '80%': '80%',\n      '85%': '85%',\n      '90%': '90%',\n      '95%': '95%',\n      '100%': '100%',\n    },\n    grayscale: {\n      0: '0',\n      DEFAULT: '100%',\n    },\n    gridAutoColumns: {\n      auto: 'auto',\n      min: 'min-content',\n      max: 'max-content',\n      fr: 'minmax(0, 1fr)',\n    },\n    gridAutoRows: {\n      auto: 'auto',\n      min: 'min-content',\n      max: 'max-content',\n      fr: 'minmax(0, 1fr)',\n    },\n    gridColumn: {\n      auto: 'auto',\n      'span-1': 'span 1 / span 1',\n      'span-2': 'span 2 / span 2',\n      'span-3': 'span 3 / span 3',\n      'span-4': 'span 4 / span 4',\n      'span-5': 'span 5 / span 5',\n      'span-6': 'span 6 / span 6',\n      'span-7': 'span 7 / span 7',\n      'span-8': 'span 8 / span 8',\n      'span-9': 'span 9 / span 9',\n      'span-10': 'span 10 / span 10',\n      'span-11': 'span 11 / span 11',\n      'span-12': 'span 12 / span 12',\n      'span-full': '1 / -1',\n    },\n    gridColumnEnd: {\n      auto: 'auto',\n      1: '1',\n      2: '2',\n      3: '3',\n      4: '4',\n      5: '5',\n      6: '6',\n      7: '7',\n      8: '8',\n      9: '9',\n      10: '10',\n      11: '11',\n      12: '12',\n      13: '13',\n    },\n    gridColumnStart: {\n      auto: 'auto',\n      1: '1',\n      2: '2',\n      3: '3',\n      4: '4',\n      5: '5',\n      6: '6',\n      7: '7',\n      8: '8',\n      9: '9',\n      10: '10',\n      11: '11',\n      12: '12',\n      13: '13',\n    },\n    gridRow: {\n      auto: 'auto',\n      'span-1': 'span 1 / span 1',\n      'span-2': 'span 2 / span 2',\n      'span-3': 'span 3 / span 3',\n      'span-4': 'span 4 / span 4',\n      'span-5': 'span 5 / span 5',\n      'span-6': 'span 6 / span 6',\n      'span-7': 'span 7 / span 7',\n      'span-8': 'span 8 / span 8',\n      'span-9': 'span 9 / span 9',\n      'span-10': 'span 10 / span 10',\n      'span-11': 'span 11 / span 11',\n      'span-12': 'span 12 / span 12',\n      'span-full': '1 / -1',\n    },\n    gridRowEnd: {\n      auto: 'auto',\n      1: '1',\n      2: '2',\n      3: '3',\n      4: '4',\n      5: '5',\n      6: '6',\n      7: '7',\n      8: '8',\n      9: '9',\n      10: '10',\n      11: '11',\n      12: '12',\n      13: '13',\n    },\n    gridRowStart: {\n      auto: 'auto',\n      1: '1',\n      2: '2',\n      3: '3',\n      4: '4',\n      5: '5',\n      6: '6',\n      7: '7',\n      8: '8',\n      9: '9',\n      10: '10',\n      11: '11',\n      12: '12',\n      13: '13',\n    },\n    gridTemplateColumns: {\n      none: 'none',\n      subgrid: 'subgrid',\n      1: 'repeat(1, minmax(0, 1fr))',\n      2: 'repeat(2, minmax(0, 1fr))',\n      3: 'repeat(3, minmax(0, 1fr))',\n      4: 'repeat(4, minmax(0, 1fr))',\n      5: 'repeat(5, minmax(0, 1fr))',\n      6: 'repeat(6, minmax(0, 1fr))',\n      7: 'repeat(7, minmax(0, 1fr))',\n      8: 'repeat(8, minmax(0, 1fr))',\n      9: 'repeat(9, minmax(0, 1fr))',\n      10: 'repeat(10, minmax(0, 1fr))',\n      11: 'repeat(11, minmax(0, 1fr))',\n      12: 'repeat(12, minmax(0, 1fr))',\n    },\n    gridTemplateRows: {\n      none: 'none',\n      subgrid: 'subgrid',\n      1: 'repeat(1, minmax(0, 1fr))',\n      2: 'repeat(2, minmax(0, 1fr))',\n      3: 'repeat(3, minmax(0, 1fr))',\n      4: 'repeat(4, minmax(0, 1fr))',\n      5: 'repeat(5, minmax(0, 1fr))',\n      6: 'repeat(6, minmax(0, 1fr))',\n      7: 'repeat(7, minmax(0, 1fr))',\n      8: 'repeat(8, minmax(0, 1fr))',\n      9: 'repeat(9, minmax(0, 1fr))',\n      10: 'repeat(10, minmax(0, 1fr))',\n      11: 'repeat(11, minmax(0, 1fr))',\n      12: 'repeat(12, minmax(0, 1fr))',\n    },\n    height: ({ theme }) => ({\n      auto: 'auto',\n      ...theme('spacing'),\n      '1/2': '50%',\n      '1/3': '33.333333%',\n      '2/3': '66.666667%',\n      '1/4': '25%',\n      '2/4': '50%',\n      '3/4': '75%',\n      '1/5': '20%',\n      '2/5': '40%',\n      '3/5': '60%',\n      '4/5': '80%',\n      '1/6': '16.666667%',\n      '2/6': '33.333333%',\n      '3/6': '50%',\n      '4/6': '66.666667%',\n      '5/6': '83.333333%',\n      full: '100%',\n      screen: '100vh',\n      svh: '100svh',\n      lvh: '100lvh',\n      dvh: '100dvh',\n      min: 'min-content',\n      max: 'max-content',\n      fit: 'fit-content',\n    }),\n    hueRotate: {\n      0: '0deg',\n      15: '15deg',\n      30: '30deg',\n      60: '60deg',\n      90: '90deg',\n      180: '180deg',\n    },\n    inset: ({ theme }) => ({\n      auto: 'auto',\n      ...theme('spacing'),\n      '1/2': '50%',\n      '1/3': '33.333333%',\n      '2/3': '66.666667%',\n      '1/4': '25%',\n      '2/4': '50%',\n      '3/4': '75%',\n      full: '100%',\n    }),\n    invert: {\n      0: '0',\n      DEFAULT: '100%',\n    },\n    keyframes: {\n      spin: {\n        to: {\n          transform: 'rotate(360deg)',\n        },\n      },\n      ping: {\n        '75%, 100%': {\n          transform: 'scale(2)',\n          opacity: '0',\n        },\n      },\n      pulse: {\n        '50%': {\n          opacity: '.5',\n        },\n      },\n      bounce: {\n        '0%, 100%': {\n          transform: 'translateY(-25%)',\n          animationTimingFunction: 'cubic-bezier(0.8,0,1,1)',\n        },\n        '50%': {\n          transform: 'none',\n          animationTimingFunction: 'cubic-bezier(0,0,0.2,1)',\n        },\n      },\n    },\n    letterSpacing: {\n      tighter: '-0.05em',\n      tight: '-0.025em',\n      normal: '0em',\n      wide: '0.025em',\n      wider: '0.05em',\n      widest: '0.1em',\n    },\n    lineHeight: {\n      none: '1',\n      tight: '1.25',\n      snug: '1.375',\n      normal: '1.5',\n      relaxed: '1.625',\n      loose: '2',\n      3: '.75rem',\n      4: '1rem',\n      5: '1.25rem',\n      6: '1.5rem',\n      7: '1.75rem',\n      8: '2rem',\n      9: '2.25rem',\n      10: '2.5rem',\n    },\n    listStyleType: {\n      none: 'none',\n      disc: 'disc',\n      decimal: 'decimal',\n    },\n    listStyleImage: {\n      none: 'none',\n    },\n    margin: ({ theme }) => ({\n      auto: 'auto',\n      ...theme('spacing'),\n    }),\n    lineClamp: {\n      1: '1',\n      2: '2',\n      3: '3',\n      4: '4',\n      5: '5',\n      6: '6',\n    },\n    maxHeight: ({ theme }) => ({\n      ...theme('spacing'),\n      none: 'none',\n      full: '100%',\n      screen: '100vh',\n      svh: '100svh',\n      lvh: '100lvh',\n      dvh: '100dvh',\n      min: 'min-content',\n      max: 'max-content',\n      fit: 'fit-content',\n    }),\n    maxWidth: ({ theme, breakpoints }) => ({\n      ...theme('spacing'),\n      none: 'none',\n      xs: '20rem',\n      sm: '24rem',\n      md: '28rem',\n      lg: '32rem',\n      xl: '36rem',\n      '2xl': '42rem',\n      '3xl': '48rem',\n      '4xl': '56rem',\n      '5xl': '64rem',\n      '6xl': '72rem',\n      '7xl': '80rem',\n      full: '100%',\n      min: 'min-content',\n      max: 'max-content',\n      fit: 'fit-content',\n      prose: '65ch',\n      ...breakpoints(theme('screens')),\n    }),\n    minHeight: ({ theme }) => ({\n      ...theme('spacing'),\n      full: '100%',\n      screen: '100vh',\n      svh: '100svh',\n      lvh: '100lvh',\n      dvh: '100dvh',\n      min: 'min-content',\n      max: 'max-content',\n      fit: 'fit-content',\n    }),\n    minWidth: ({ theme }) => ({\n      ...theme('spacing'),\n      full: '100%',\n      min: 'min-content',\n      max: 'max-content',\n      fit: 'fit-content',\n    }),\n    objectPosition: {\n      bottom: 'bottom',\n      center: 'center',\n      left: 'left',\n      'left-bottom': 'left bottom',\n      'left-top': 'left top',\n      right: 'right',\n      'right-bottom': 'right bottom',\n      'right-top': 'right top',\n      top: 'top',\n    },\n    opacity: {\n      0: '0',\n      5: '0.05',\n      10: '0.1',\n      15: '0.15',\n      20: '0.2',\n      25: '0.25',\n      30: '0.3',\n      35: '0.35',\n      40: '0.4',\n      45: '0.45',\n      50: '0.5',\n      55: '0.55',\n      60: '0.6',\n      65: '0.65',\n      70: '0.7',\n      75: '0.75',\n      80: '0.8',\n      85: '0.85',\n      90: '0.9',\n      95: '0.95',\n      100: '1',\n    },\n    order: {\n      first: '-9999',\n      last: '9999',\n      none: '0',\n      1: '1',\n      2: '2',\n      3: '3',\n      4: '4',\n      5: '5',\n      6: '6',\n      7: '7',\n      8: '8',\n      9: '9',\n      10: '10',\n      11: '11',\n      12: '12',\n    },\n    outlineColor: ({ theme }) => theme('colors'),\n    outlineOffset: {\n      0: '0px',\n      1: '1px',\n      2: '2px',\n      4: '4px',\n      8: '8px',\n    },\n    outlineWidth: {\n      0: '0px',\n      1: '1px',\n      2: '2px',\n      4: '4px',\n      8: '8px',\n    },\n    padding: ({ theme }) => theme('spacing'),\n    placeholderColor: ({ theme }) => theme('colors'),\n    placeholderOpacity: ({ theme }) => theme('opacity'),\n    ringColor: ({ theme }) => ({\n      DEFAULT: theme('colors.blue.500', '#3b82f6'),\n      ...theme('colors'),\n    }),\n    ringOffsetColor: ({ theme }) => theme('colors'),\n    ringOffsetWidth: {\n      0: '0px',\n      1: '1px',\n      2: '2px',\n      4: '4px',\n      8: '8px',\n    },\n    ringOpacity: ({ theme }) => ({\n      DEFAULT: '0.5',\n      ...theme('opacity'),\n    }),\n    ringWidth: {\n      DEFAULT: '3px',\n      0: '0px',\n      1: '1px',\n      2: '2px',\n      4: '4px',\n      8: '8px',\n    },\n    rotate: {\n      0: '0deg',\n      1: '1deg',\n      2: '2deg',\n      3: '3deg',\n      6: '6deg',\n      12: '12deg',\n      45: '45deg',\n      90: '90deg',\n      180: '180deg',\n    },\n    saturate: {\n      0: '0',\n      50: '.5',\n      100: '1',\n      150: '1.5',\n      200: '2',\n    },\n    scale: {\n      0: '0',\n      50: '.5',\n      75: '.75',\n      90: '.9',\n      95: '.95',\n      100: '1',\n      105: '1.05',\n      110: '1.1',\n      125: '1.25',\n      150: '1.5',\n    },\n    screens: {\n      sm: '640px',\n      md: '768px',\n      lg: '1024px',\n      xl: '1280px',\n      '2xl': '1536px',\n    },\n    scrollMargin: ({ theme }) => ({\n      ...theme('spacing'),\n    }),\n    scrollPadding: ({ theme }) => theme('spacing'),\n    sepia: {\n      0: '0',\n      DEFAULT: '100%',\n    },\n    skew: {\n      0: '0deg',\n      1: '1deg',\n      2: '2deg',\n      3: '3deg',\n      6: '6deg',\n      12: '12deg',\n    },\n    space: ({ theme }) => ({\n      ...theme('spacing'),\n    }),\n    spacing: {\n      px: '1px',\n      0: '0px',\n      0.5: '0.125rem',\n      1: '0.25rem',\n      1.5: '0.375rem',\n      2: '0.5rem',\n      2.5: '0.625rem',\n      3: '0.75rem',\n      3.5: '0.875rem',\n      4: '1rem',\n      5: '1.25rem',\n      6: '1.5rem',\n      7: '1.75rem',\n      8: '2rem',\n      9: '2.25rem',\n      10: '2.5rem',\n      11: '2.75rem',\n      12: '3rem',\n      14: '3.5rem',\n      16: '4rem',\n      20: '5rem',\n      24: '6rem',\n      28: '7rem',\n      32: '8rem',\n      36: '9rem',\n      40: '10rem',\n      44: '11rem',\n      48: '12rem',\n      52: '13rem',\n      56: '14rem',\n      60: '15rem',\n      64: '16rem',\n      72: '18rem',\n      80: '20rem',\n      96: '24rem',\n    },\n    stroke: ({ theme }) => ({\n      none: 'none',\n      ...theme('colors'),\n    }),\n    strokeWidth: {\n      0: '0',\n      1: '1',\n      2: '2',\n    },\n    supports: {},\n    data: {},\n    textColor: ({ theme }) => theme('colors'),\n    textDecorationColor: ({ theme }) => theme('colors'),\n    textDecorationThickness: {\n      auto: 'auto',\n      'from-font': 'from-font',\n      0: '0px',\n      1: '1px',\n      2: '2px',\n      4: '4px',\n      8: '8px',\n    },\n    textIndent: ({ theme }) => ({\n      ...theme('spacing'),\n    }),\n    textOpacity: ({ theme }) => theme('opacity'),\n    textUnderlineOffset: {\n      auto: 'auto',\n      0: '0px',\n      1: '1px',\n      2: '2px',\n      4: '4px',\n      8: '8px',\n    },\n    transformOrigin: {\n      center: 'center',\n      top: 'top',\n      'top-right': 'top right',\n      right: 'right',\n      'bottom-right': 'bottom right',\n      bottom: 'bottom',\n      'bottom-left': 'bottom left',\n      left: 'left',\n      'top-left': 'top left',\n    },\n    transitionDelay: {\n      0: '0s',\n      75: '75ms',\n      100: '100ms',\n      150: '150ms',\n      200: '200ms',\n      300: '300ms',\n      500: '500ms',\n      700: '700ms',\n      1000: '1000ms',\n    },\n    transitionDuration: {\n      DEFAULT: '150ms',\n      0: '0s',\n      75: '75ms',\n      100: '100ms',\n      150: '150ms',\n      200: '200ms',\n      300: '300ms',\n      500: '500ms',\n      700: '700ms',\n      1000: '1000ms',\n    },\n    transitionProperty: {\n      none: 'none',\n      all: 'all',\n      DEFAULT:\n        'color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter',\n      colors: 'color, background-color, border-color, text-decoration-color, fill, stroke',\n      opacity: 'opacity',\n      shadow: 'box-shadow',\n      transform: 'transform',\n    },\n    transitionTimingFunction: {\n      DEFAULT: 'cubic-bezier(0.4, 0, 0.2, 1)',\n      linear: 'linear',\n      in: 'cubic-bezier(0.4, 0, 1, 1)',\n      out: 'cubic-bezier(0, 0, 0.2, 1)',\n      'in-out': 'cubic-bezier(0.4, 0, 0.2, 1)',\n    },\n    translate: ({ theme }) => ({\n      ...theme('spacing'),\n      '1/2': '50%',\n      '1/3': '33.333333%',\n      '2/3': '66.666667%',\n      '1/4': '25%',\n      '2/4': '50%',\n      '3/4': '75%',\n      full: '100%',\n    }),\n    size: ({ theme }) => ({\n      auto: 'auto',\n      ...theme('spacing'),\n      '1/2': '50%',\n      '1/3': '33.333333%',\n      '2/3': '66.666667%',\n      '1/4': '25%',\n      '2/4': '50%',\n      '3/4': '75%',\n      '1/5': '20%',\n      '2/5': '40%',\n      '3/5': '60%',\n      '4/5': '80%',\n      '1/6': '16.666667%',\n      '2/6': '33.333333%',\n      '3/6': '50%',\n      '4/6': '66.666667%',\n      '5/6': '83.333333%',\n      '1/12': '8.333333%',\n      '2/12': '16.666667%',\n      '3/12': '25%',\n      '4/12': '33.333333%',\n      '5/12': '41.666667%',\n      '6/12': '50%',\n      '7/12': '58.333333%',\n      '8/12': '66.666667%',\n      '9/12': '75%',\n      '10/12': '83.333333%',\n      '11/12': '91.666667%',\n      full: '100%',\n      min: 'min-content',\n      max: 'max-content',\n      fit: 'fit-content',\n    }),\n    width: ({ theme }) => ({\n      auto: 'auto',\n      ...theme('spacing'),\n      '1/2': '50%',\n      '1/3': '33.333333%',\n      '2/3': '66.666667%',\n      '1/4': '25%',\n      '2/4': '50%',\n      '3/4': '75%',\n      '1/5': '20%',\n      '2/5': '40%',\n      '3/5': '60%',\n      '4/5': '80%',\n      '1/6': '16.666667%',\n      '2/6': '33.333333%',\n      '3/6': '50%',\n      '4/6': '66.666667%',\n      '5/6': '83.333333%',\n      '1/12': '8.333333%',\n      '2/12': '16.666667%',\n      '3/12': '25%',\n      '4/12': '33.333333%',\n      '5/12': '41.666667%',\n      '6/12': '50%',\n      '7/12': '58.333333%',\n      '8/12': '66.666667%',\n      '9/12': '75%',\n      '10/12': '83.333333%',\n      '11/12': '91.666667%',\n      full: '100%',\n      screen: '100vw',\n      svw: '100svw',\n      lvw: '100lvw',\n      dvw: '100dvw',\n      min: 'min-content',\n      max: 'max-content',\n      fit: 'fit-content',\n    }),\n    willChange: {\n      auto: 'auto',\n      scroll: 'scroll-position',\n      contents: 'contents',\n      transform: 'transform',\n    },\n    zIndex: {\n      auto: 'auto',\n      0: '0',\n      10: '10',\n      20: '20',\n      30: '30',\n      40: '40',\n      50: '50',\n    },\n  },\n  plugins: [],\n}\n", "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", {\n    value: true\n});\nObject.defineProperty(exports, \"default\", {\n    enumerable: true,\n    get: function() {\n        return _default;\n    }\n});\nconst _cloneDeep = require(\"../util/cloneDeep\");\nconst _configfull = /*#__PURE__*/ _interop_require_default(require(\"../../stubs/config.full\"));\nfunction _interop_require_default(obj) {\n    return obj && obj.__esModule ? obj : {\n        default: obj\n    };\n}\nconst _default = (0, _cloneDeep.cloneDeep)(_configfull.default.theme);\n", "let defaultTheme = require('./lib/public/default-theme')\nmodule.exports = (defaultTheme.__esModule ? defaultTheme : { default: defaultTheme }).default\n", "\nmodule.exports = function () {\n  var selection = document.getSelection();\n  if (!selection.rangeCount) {\n    return function () {};\n  }\n  var active = document.activeElement;\n\n  var ranges = [];\n  for (var i = 0; i < selection.rangeCount; i++) {\n    ranges.push(selection.getRangeAt(i));\n  }\n\n  switch (active.tagName.toUpperCase()) { // .toUpperCase handles XHTML\n    case 'INPUT':\n    case 'TEXTAREA':\n      active.blur();\n      break;\n\n    default:\n      active = null;\n      break;\n  }\n\n  selection.removeAllRanges();\n  return function () {\n    selection.type === 'Caret' &&\n    selection.removeAllRanges();\n\n    if (!selection.rangeCount) {\n      ranges.forEach(function(range) {\n        selection.addRange(range);\n      });\n    }\n\n    active &&\n    active.focus();\n  };\n};\n", "\"use strict\";\n\nvar deselectCurrent = require(\"toggle-selection\");\n\nvar clipboardToIE11Formatting = {\n  \"text/plain\": \"Text\",\n  \"text/html\": \"Url\",\n  \"default\": \"Text\"\n}\n\nvar defaultMessage = \"Copy to clipboard: #{key}, Enter\";\n\nfunction format(message) {\n  var copyKey = (/mac os x/i.test(navigator.userAgent) ? \"\u2318\" : \"Ctrl\") + \"+C\";\n  return message.replace(/#{\\s*key\\s*}/g, copyKey);\n}\n\nfunction copy(text, options) {\n  var debug,\n    message,\n    reselectPrevious,\n    range,\n    selection,\n    mark,\n    success = false;\n  if (!options) {\n    options = {};\n  }\n  debug = options.debug || false;\n  try {\n    reselectPrevious = deselectCurrent();\n\n    range = document.createRange();\n    selection = document.getSelection();\n\n    mark = document.createElement(\"span\");\n    mark.textContent = text;\n    // reset user styles for span element\n    mark.style.all = \"unset\";\n    // prevents scrolling to the end of the page\n    mark.style.position = \"fixed\";\n    mark.style.top = 0;\n    mark.style.clip = \"rect(0, 0, 0, 0)\";\n    // used to preserve spaces and line breaks\n    mark.style.whiteSpace = \"pre\";\n    // do not inherit user-select (it may be `none`)\n    mark.style.webkitUserSelect = \"text\";\n    mark.style.MozUserSelect = \"text\";\n    mark.style.msUserSelect = \"text\";\n    mark.style.userSelect = \"text\";\n    mark.addEventListener(\"copy\", function(e) {\n      e.stopPropagation();\n      if (options.format) {\n        e.preventDefault();\n        if (typeof e.clipboardData === \"undefined\") { // IE 11\n          debug && console.warn(\"unable to use e.clipboardData\");\n          debug && console.warn(\"trying IE specific stuff\");\n          window.clipboardData.clearData();\n          var format = clipboardToIE11Formatting[options.format] || clipboardToIE11Formatting[\"default\"]\n          window.clipboardData.setData(format, text);\n        } else { // all other browsers\n          e.clipboardData.clearData();\n          e.clipboardData.setData(options.format, text);\n        }\n      }\n      if (options.onCopy) {\n        e.preventDefault();\n        options.onCopy(e.clipboardData);\n      }\n    });\n\n    document.body.appendChild(mark);\n\n    range.selectNodeContents(mark);\n    selection.addRange(range);\n\n    var successful = document.execCommand(\"copy\");\n    if (!successful) {\n      throw new Error(\"copy command was unsuccessful\");\n    }\n    success = true;\n  } catch (err) {\n    debug && console.error(\"unable to copy using execCommand: \", err);\n    debug && console.warn(\"trying IE specific stuff\");\n    try {\n      window.clipboardData.setData(options.format || \"text\", text);\n      options.onCopy && options.onCopy(window.clipboardData);\n      success = true;\n    } catch (err) {\n      debug && console.error(\"unable to copy using clipboardData: \", err);\n      debug && console.error(\"falling back to prompt\");\n      message = format(\"message\" in options ? options.message : defaultMessage);\n      window.prompt(message, text);\n    }\n  } finally {\n    if (selection) {\n      if (typeof selection.removeRange == \"function\") {\n        selection.removeRange(range);\n      } else {\n        selection.removeAllRanges();\n      }\n    }\n\n    if (mark) {\n      document.body.removeChild(mark);\n    }\n    reselectPrevious();\n  }\n\n  return success;\n}\n\nmodule.exports = copy;\n", "typeof navigator === \"object\" && (function (global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n  typeof define === 'function' && define.amd ? define('Plyr', factory) :\n  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Plyr = factory());\n})(this, (function () { 'use strict';\n\n  function _defineProperty$1(obj, key, value) {\n    if (key in obj) {\n      Object.defineProperty(obj, key, {\n        value: value,\n        enumerable: true,\n        configurable: true,\n        writable: true\n      });\n    } else {\n      obj[key] = value;\n    }\n\n    return obj;\n  }\n\n  function _classCallCheck(e, t) {\n    if (!(e instanceof t)) throw new TypeError(\"Cannot call a class as a function\");\n  }\n\n  function _defineProperties(e, t) {\n    for (var n = 0; n < t.length; n++) {\n      var r = t[n];\n      r.enumerable = r.enumerable || !1, r.configurable = !0, \"value\" in r && (r.writable = !0), Object.defineProperty(e, r.key, r);\n    }\n  }\n\n  function _createClass(e, t, n) {\n    return t && _defineProperties(e.prototype, t), n && _defineProperties(e, n), e;\n  }\n\n  function _defineProperty(e, t, n) {\n    return t in e ? Object.defineProperty(e, t, {\n      value: n,\n      enumerable: !0,\n      configurable: !0,\n      writable: !0\n    }) : e[t] = n, e;\n  }\n\n  function ownKeys(e, t) {\n    var n = Object.keys(e);\n\n    if (Object.getOwnPropertySymbols) {\n      var r = Object.getOwnPropertySymbols(e);\n      t && (r = r.filter(function (t) {\n        return Object.getOwnPropertyDescriptor(e, t).enumerable;\n      })), n.push.apply(n, r);\n    }\n\n    return n;\n  }\n\n  function _objectSpread2(e) {\n    for (var t = 1; t < arguments.length; t++) {\n      var n = null != arguments[t] ? arguments[t] : {};\n      t % 2 ? ownKeys(Object(n), !0).forEach(function (t) {\n        _defineProperty(e, t, n[t]);\n      }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(n)) : ownKeys(Object(n)).forEach(function (t) {\n        Object.defineProperty(e, t, Object.getOwnPropertyDescriptor(n, t));\n      });\n    }\n\n    return e;\n  }\n\n  var defaults$1 = {\n    addCSS: !0,\n    thumbWidth: 15,\n    watch: !0\n  };\n\n  function matches$1(e, t) {\n    return function () {\n      return Array.from(document.querySelectorAll(t)).includes(this);\n    }.call(e, t);\n  }\n\n  function trigger(e, t) {\n    if (e && t) {\n      var n = new Event(t, {\n        bubbles: !0\n      });\n      e.dispatchEvent(n);\n    }\n  }\n\n  var getConstructor$1 = function (e) {\n    return null != e ? e.constructor : null;\n  },\n      instanceOf$1 = function (e, t) {\n    return !!(e && t && e instanceof t);\n  },\n      isNullOrUndefined$1 = function (e) {\n    return null == e;\n  },\n      isObject$1 = function (e) {\n    return getConstructor$1(e) === Object;\n  },\n      isNumber$1 = function (e) {\n    return getConstructor$1(e) === Number && !Number.isNaN(e);\n  },\n      isString$1 = function (e) {\n    return getConstructor$1(e) === String;\n  },\n      isBoolean$1 = function (e) {\n    return getConstructor$1(e) === Boolean;\n  },\n      isFunction$1 = function (e) {\n    return getConstructor$1(e) === Function;\n  },\n      isArray$1 = function (e) {\n    return Array.isArray(e);\n  },\n      isNodeList$1 = function (e) {\n    return instanceOf$1(e, NodeList);\n  },\n      isElement$1 = function (e) {\n    return instanceOf$1(e, Element);\n  },\n      isEvent$1 = function (e) {\n    return instanceOf$1(e, Event);\n  },\n      isEmpty$1 = function (e) {\n    return isNullOrUndefined$1(e) || (isString$1(e) || isArray$1(e) || isNodeList$1(e)) && !e.length || isObject$1(e) && !Object.keys(e).length;\n  },\n      is$1 = {\n    nullOrUndefined: isNullOrUndefined$1,\n    object: isObject$1,\n    number: isNumber$1,\n    string: isString$1,\n    boolean: isBoolean$1,\n    function: isFunction$1,\n    array: isArray$1,\n    nodeList: isNodeList$1,\n    element: isElement$1,\n    event: isEvent$1,\n    empty: isEmpty$1\n  };\n\n  function getDecimalPlaces(e) {\n    var t = \"\".concat(e).match(/(?:\\.(\\d+))?(?:[eE]([+-]?\\d+))?$/);\n    return t ? Math.max(0, (t[1] ? t[1].length : 0) - (t[2] ? +t[2] : 0)) : 0;\n  }\n\n  function round(e, t) {\n    if (1 > t) {\n      var n = getDecimalPlaces(t);\n      return parseFloat(e.toFixed(n));\n    }\n\n    return Math.round(e / t) * t;\n  }\n\n  var RangeTouch = function () {\n    function e(t, n) {\n      _classCallCheck(this, e), is$1.element(t) ? this.element = t : is$1.string(t) && (this.element = document.querySelector(t)), is$1.element(this.element) && is$1.empty(this.element.rangeTouch) && (this.config = _objectSpread2({}, defaults$1, {}, n), this.init());\n    }\n\n    return _createClass(e, [{\n      key: \"init\",\n      value: function () {\n        e.enabled && (this.config.addCSS && (this.element.style.userSelect = \"none\", this.element.style.webKitUserSelect = \"none\", this.element.style.touchAction = \"manipulation\"), this.listeners(!0), this.element.rangeTouch = this);\n      }\n    }, {\n      key: \"destroy\",\n      value: function () {\n        e.enabled && (this.config.addCSS && (this.element.style.userSelect = \"\", this.element.style.webKitUserSelect = \"\", this.element.style.touchAction = \"\"), this.listeners(!1), this.element.rangeTouch = null);\n      }\n    }, {\n      key: \"listeners\",\n      value: function (e) {\n        var t = this,\n            n = e ? \"addEventListener\" : \"removeEventListener\";\n        [\"touchstart\", \"touchmove\", \"touchend\"].forEach(function (e) {\n          t.element[n](e, function (e) {\n            return t.set(e);\n          }, !1);\n        });\n      }\n    }, {\n      key: \"get\",\n      value: function (t) {\n        if (!e.enabled || !is$1.event(t)) return null;\n        var n,\n            r = t.target,\n            i = t.changedTouches[0],\n            o = parseFloat(r.getAttribute(\"min\")) || 0,\n            s = parseFloat(r.getAttribute(\"max\")) || 100,\n            u = parseFloat(r.getAttribute(\"step\")) || 1,\n            c = r.getBoundingClientRect(),\n            a = 100 / c.width * (this.config.thumbWidth / 2) / 100;\n        return 0 > (n = 100 / c.width * (i.clientX - c.left)) ? n = 0 : 100 < n && (n = 100), 50 > n ? n -= (100 - 2 * n) * a : 50 < n && (n += 2 * (n - 50) * a), o + round(n / 100 * (s - o), u);\n      }\n    }, {\n      key: \"set\",\n      value: function (t) {\n        e.enabled && is$1.event(t) && !t.target.disabled && (t.preventDefault(), t.target.value = this.get(t), trigger(t.target, \"touchend\" === t.type ? \"change\" : \"input\"));\n      }\n    }], [{\n      key: \"setup\",\n      value: function (t) {\n        var n = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : {},\n            r = null;\n        if (is$1.empty(t) || is$1.string(t) ? r = Array.from(document.querySelectorAll(is$1.string(t) ? t : 'input[type=\"range\"]')) : is$1.element(t) ? r = [t] : is$1.nodeList(t) ? r = Array.from(t) : is$1.array(t) && (r = t.filter(is$1.element)), is$1.empty(r)) return null;\n\n        var i = _objectSpread2({}, defaults$1, {}, n);\n\n        if (is$1.string(t) && i.watch) {\n          var o = new MutationObserver(function (n) {\n            Array.from(n).forEach(function (n) {\n              Array.from(n.addedNodes).forEach(function (n) {\n                is$1.element(n) && matches$1(n, t) && new e(n, i);\n              });\n            });\n          });\n          o.observe(document.body, {\n            childList: !0,\n            subtree: !0\n          });\n        }\n\n        return r.map(function (t) {\n          return new e(t, n);\n        });\n      }\n    }, {\n      key: \"enabled\",\n      get: function () {\n        return \"ontouchstart\" in document.documentElement;\n      }\n    }]), e;\n  }();\n\n  // ==========================================================================\n  // Type checking utils\n  // ==========================================================================\n  const getConstructor = input => input !== null && typeof input !== 'undefined' ? input.constructor : null;\n\n  const instanceOf = (input, constructor) => Boolean(input && constructor && input instanceof constructor);\n\n  const isNullOrUndefined = input => input === null || typeof input === 'undefined';\n\n  const isObject = input => getConstructor(input) === Object;\n\n  const isNumber = input => getConstructor(input) === Number && !Number.isNaN(input);\n\n  const isString = input => getConstructor(input) === String;\n\n  const isBoolean = input => getConstructor(input) === Boolean;\n\n  const isFunction = input => getConstructor(input) === Function;\n\n  const isArray = input => Array.isArray(input);\n\n  const isWeakMap = input => instanceOf(input, WeakMap);\n\n  const isNodeList = input => instanceOf(input, NodeList);\n\n  const isTextNode = input => getConstructor(input) === Text;\n\n  const isEvent = input => instanceOf(input, Event);\n\n  const isKeyboardEvent = input => instanceOf(input, KeyboardEvent);\n\n  const isCue = input => instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue);\n\n  const isTrack = input => instanceOf(input, TextTrack) || !isNullOrUndefined(input) && isString(input.kind);\n\n  const isPromise = input => instanceOf(input, Promise) && isFunction(input.then);\n\n  const isElement = input => input !== null && typeof input === 'object' && input.nodeType === 1 && typeof input.style === 'object' && typeof input.ownerDocument === 'object';\n\n  const isEmpty = input => isNullOrUndefined(input) || (isString(input) || isArray(input) || isNodeList(input)) && !input.length || isObject(input) && !Object.keys(input).length;\n\n  const isUrl = input => {\n    // Accept a URL object\n    if (instanceOf(input, window.URL)) {\n      return true;\n    } // Must be string from here\n\n\n    if (!isString(input)) {\n      return false;\n    } // Add the protocol if required\n\n\n    let string = input;\n\n    if (!input.startsWith('http://') || !input.startsWith('https://')) {\n      string = `http://${input}`;\n    }\n\n    try {\n      return !isEmpty(new URL(string).hostname);\n    } catch (_) {\n      return false;\n    }\n  };\n\n  var is = {\n    nullOrUndefined: isNullOrUndefined,\n    object: isObject,\n    number: isNumber,\n    string: isString,\n    boolean: isBoolean,\n    function: isFunction,\n    array: isArray,\n    weakMap: isWeakMap,\n    nodeList: isNodeList,\n    element: isElement,\n    textNode: isTextNode,\n    event: isEvent,\n    keyboardEvent: isKeyboardEvent,\n    cue: isCue,\n    track: isTrack,\n    promise: isPromise,\n    url: isUrl,\n    empty: isEmpty\n  };\n\n  // ==========================================================================\n  const transitionEndEvent = (() => {\n    const element = document.createElement('span');\n    const events = {\n      WebkitTransition: 'webkitTransitionEnd',\n      MozTransition: 'transitionend',\n      OTransition: 'oTransitionEnd otransitionend',\n      transition: 'transitionend'\n    };\n    const type = Object.keys(events).find(event => element.style[event] !== undefined);\n    return is.string(type) ? events[type] : false;\n  })(); // Force repaint of element\n\n  function repaint(element, delay) {\n    setTimeout(() => {\n      try {\n        // eslint-disable-next-line no-param-reassign\n        element.hidden = true; // eslint-disable-next-line no-unused-expressions\n\n        element.offsetHeight; // eslint-disable-next-line no-param-reassign\n\n        element.hidden = false;\n      } catch (_) {// Do nothing\n      }\n    }, delay);\n  }\n\n  // ==========================================================================\n  // Browser sniffing\n  // Unfortunately, due to mixed support, UA sniffing is required\n  // ==========================================================================\n  const browser = {\n    isIE: Boolean(window.document.documentMode),\n    isEdge: window.navigator.userAgent.includes('Edge'),\n    isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent),\n    isIPhone: /(iPhone|iPod)/gi.test(navigator.platform),\n    isIos: navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1 || /(iPad|iPhone|iPod)/gi.test(navigator.platform)\n  };\n\n  // ==========================================================================\n\n  function cloneDeep(object) {\n    return JSON.parse(JSON.stringify(object));\n  } // Get a nested value in an object\n\n  function getDeep(object, path) {\n    return path.split('.').reduce((obj, key) => obj && obj[key], object);\n  } // Deep extend destination object with N more objects\n\n  function extend(target = {}, ...sources) {\n    if (!sources.length) {\n      return target;\n    }\n\n    const source = sources.shift();\n\n    if (!is.object(source)) {\n      return target;\n    }\n\n    Object.keys(source).forEach(key => {\n      if (is.object(source[key])) {\n        if (!Object.keys(target).includes(key)) {\n          Object.assign(target, {\n            [key]: {}\n          });\n        }\n\n        extend(target[key], source[key]);\n      } else {\n        Object.assign(target, {\n          [key]: source[key]\n        });\n      }\n    });\n    return extend(target, ...sources);\n  }\n\n  // ==========================================================================\n\n  function wrap(elements, wrapper) {\n    // Convert `elements` to an array, if necessary.\n    const targets = elements.length ? elements : [elements]; // Loops backwards to prevent having to clone the wrapper on the\n    // first element (see `child` below).\n\n    Array.from(targets).reverse().forEach((element, index) => {\n      const child = index > 0 ? wrapper.cloneNode(true) : wrapper; // Cache the current parent and sibling.\n\n      const parent = element.parentNode;\n      const sibling = element.nextSibling; // Wrap the element (is automatically removed from its current\n      // parent).\n\n      child.appendChild(element); // If the element had a sibling, insert the wrapper before\n      // the sibling to maintain the HTML structure; otherwise, just\n      // append it to the parent.\n\n      if (sibling) {\n        parent.insertBefore(child, sibling);\n      } else {\n        parent.appendChild(child);\n      }\n    });\n  } // Set attributes\n\n  function setAttributes(element, attributes) {\n    if (!is.element(element) || is.empty(attributes)) {\n      return;\n    } // Assume null and undefined attributes should be left out,\n    // Setting them would otherwise convert them to \"null\" and \"undefined\"\n\n\n    Object.entries(attributes).filter(([, value]) => !is.nullOrUndefined(value)).forEach(([key, value]) => element.setAttribute(key, value));\n  } // Create a DocumentFragment\n\n  function createElement(type, attributes, text) {\n    // Create a new <element>\n    const element = document.createElement(type); // Set all passed attributes\n\n    if (is.object(attributes)) {\n      setAttributes(element, attributes);\n    } // Add text node\n\n\n    if (is.string(text)) {\n      element.innerText = text;\n    } // Return built element\n\n\n    return element;\n  } // Inaert an element after another\n\n  function insertAfter(element, target) {\n    if (!is.element(element) || !is.element(target)) {\n      return;\n    }\n\n    target.parentNode.insertBefore(element, target.nextSibling);\n  } // Insert a DocumentFragment\n\n  function insertElement(type, parent, attributes, text) {\n    if (!is.element(parent)) {\n      return;\n    }\n\n    parent.appendChild(createElement(type, attributes, text));\n  } // Remove element(s)\n\n  function removeElement(element) {\n    if (is.nodeList(element) || is.array(element)) {\n      Array.from(element).forEach(removeElement);\n      return;\n    }\n\n    if (!is.element(element) || !is.element(element.parentNode)) {\n      return;\n    }\n\n    element.parentNode.removeChild(element);\n  } // Remove all child elements\n\n  function emptyElement(element) {\n    if (!is.element(element)) {\n      return;\n    }\n\n    let {\n      length\n    } = element.childNodes;\n\n    while (length > 0) {\n      element.removeChild(element.lastChild);\n      length -= 1;\n    }\n  } // Replace element\n\n  function replaceElement(newChild, oldChild) {\n    if (!is.element(oldChild) || !is.element(oldChild.parentNode) || !is.element(newChild)) {\n      return null;\n    }\n\n    oldChild.parentNode.replaceChild(newChild, oldChild);\n    return newChild;\n  } // Get an attribute object from a string selector\n\n  function getAttributesFromSelector(sel, existingAttributes) {\n    // For example:\n    // '.test' to { class: 'test' }\n    // '#test' to { id: 'test' }\n    // '[data-test=\"test\"]' to { 'data-test': 'test' }\n    if (!is.string(sel) || is.empty(sel)) {\n      return {};\n    }\n\n    const attributes = {};\n    const existing = extend({}, existingAttributes);\n    sel.split(',').forEach(s => {\n      // Remove whitespace\n      const selector = s.trim();\n      const className = selector.replace('.', '');\n      const stripped = selector.replace(/[[\\]]/g, ''); // Get the parts and value\n\n      const parts = stripped.split('=');\n      const [key] = parts;\n      const value = parts.length > 1 ? parts[1].replace(/[\"']/g, '') : ''; // Get the first character\n\n      const start = selector.charAt(0);\n\n      switch (start) {\n        case '.':\n          // Add to existing classname\n          if (is.string(existing.class)) {\n            attributes.class = `${existing.class} ${className}`;\n          } else {\n            attributes.class = className;\n          }\n\n          break;\n\n        case '#':\n          // ID selector\n          attributes.id = selector.replace('#', '');\n          break;\n\n        case '[':\n          // Attribute selector\n          attributes[key] = value;\n          break;\n      }\n    });\n    return extend(existing, attributes);\n  } // Toggle hidden\n\n  function toggleHidden(element, hidden) {\n    if (!is.element(element)) {\n      return;\n    }\n\n    let hide = hidden;\n\n    if (!is.boolean(hide)) {\n      hide = !element.hidden;\n    } // eslint-disable-next-line no-param-reassign\n\n\n    element.hidden = hide;\n  } // Mirror Element.classList.toggle, with IE compatibility for \"force\" argument\n\n  function toggleClass(element, className, force) {\n    if (is.nodeList(element)) {\n      return Array.from(element).map(e => toggleClass(e, className, force));\n    }\n\n    if (is.element(element)) {\n      let method = 'toggle';\n\n      if (typeof force !== 'undefined') {\n        method = force ? 'add' : 'remove';\n      }\n\n      element.classList[method](className);\n      return element.classList.contains(className);\n    }\n\n    return false;\n  } // Has class name\n\n  function hasClass(element, className) {\n    return is.element(element) && element.classList.contains(className);\n  } // Element matches selector\n\n  function matches(element, selector) {\n    const {\n      prototype\n    } = Element;\n\n    function match() {\n      return Array.from(document.querySelectorAll(selector)).includes(this);\n    }\n\n    const method = prototype.matches || prototype.webkitMatchesSelector || prototype.mozMatchesSelector || prototype.msMatchesSelector || match;\n    return method.call(element, selector);\n  } // Closest ancestor element matching selector (also tests element itself)\n\n  function closest$1(element, selector) {\n    const {\n      prototype\n    } = Element; // https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill\n\n    function closestElement() {\n      let el = this;\n\n      do {\n        if (matches.matches(el, selector)) return el;\n        el = el.parentElement || el.parentNode;\n      } while (el !== null && el.nodeType === 1);\n\n      return null;\n    }\n\n    const method = prototype.closest || closestElement;\n    return method.call(element, selector);\n  } // Find all elements\n\n  function getElements(selector) {\n    return this.elements.container.querySelectorAll(selector);\n  } // Find a single element\n\n  function getElement(selector) {\n    return this.elements.container.querySelector(selector);\n  } // Set focus and tab focus class\n\n  function setFocus(element = null, tabFocus = false) {\n    if (!is.element(element)) {\n      return;\n    } // Set regular focus\n\n\n    element.focus({\n      preventScroll: true\n    }); // If we want to mimic keyboard focus via tab\n\n    if (tabFocus) {\n      toggleClass(element, this.config.classNames.tabFocus);\n    }\n  }\n\n  // ==========================================================================\n\n  const defaultCodecs = {\n    'audio/ogg': 'vorbis',\n    'audio/wav': '1',\n    'video/webm': 'vp8, vorbis',\n    'video/mp4': 'avc1.42E01E, mp4a.40.2',\n    'video/ogg': 'theora'\n  }; // Check for feature support\n\n  const support = {\n    // Basic support\n    audio: 'canPlayType' in document.createElement('audio'),\n    video: 'canPlayType' in document.createElement('video'),\n\n    // Check for support\n    // Basic functionality vs full UI\n    check(type, provider, playsinline) {\n      const canPlayInline = browser.isIPhone && playsinline && support.playsinline;\n      const api = support[type] || provider !== 'html5';\n      const ui = api && support.rangeInput && (type !== 'video' || !browser.isIPhone || canPlayInline);\n      return {\n        api,\n        ui\n      };\n    },\n\n    // Picture-in-picture support\n    // Safari & Chrome only currently\n    pip: (() => {\n      if (browser.isIPhone) {\n        return false;\n      } // Safari\n      // https://developer.apple.com/documentation/webkitjs/adding_picture_in_picture_to_your_safari_media_controls\n\n\n      if (is.function(createElement('video').webkitSetPresentationMode)) {\n        return true;\n      } // Chrome\n      // https://developers.google.com/web/updates/2018/10/watch-video-using-picture-in-picture\n\n\n      if (document.pictureInPictureEnabled && !createElement('video').disablePictureInPicture) {\n        return true;\n      }\n\n      return false;\n    })(),\n    // Airplay support\n    // Safari only currently\n    airplay: is.function(window.WebKitPlaybackTargetAvailabilityEvent),\n    // Inline playback support\n    // https://webkit.org/blog/6784/new-video-policies-for-ios/\n    playsinline: 'playsInline' in document.createElement('video'),\n\n    // Check for mime type support against a player instance\n    // Credits: http://diveintohtml5.info/everything.html\n    // Related: http://www.leanbackplayer.com/test/h5mt.html\n    mime(input) {\n      if (is.empty(input)) {\n        return false;\n      }\n\n      const [mediaType] = input.split('/');\n      let type = input; // Verify we're using HTML5 and there's no media type mismatch\n\n      if (!this.isHTML5 || mediaType !== this.type) {\n        return false;\n      } // Add codec if required\n\n\n      if (Object.keys(defaultCodecs).includes(type)) {\n        type += `; codecs=\"${defaultCodecs[input]}\"`;\n      }\n\n      try {\n        return Boolean(type && this.media.canPlayType(type).replace(/no/, ''));\n      } catch (_) {\n        return false;\n      }\n    },\n\n    // Check for textTracks support\n    textTracks: 'textTracks' in document.createElement('video'),\n    // <input type=\"range\"> Sliders\n    rangeInput: (() => {\n      const range = document.createElement('input');\n      range.type = 'range';\n      return range.type === 'range';\n    })(),\n    // Touch\n    // NOTE: Remember a device can be mouse + touch enabled so we check on first touch event\n    touch: 'ontouchstart' in document.documentElement,\n    // Detect transitions support\n    transitions: transitionEndEvent !== false,\n    // Reduced motion iOS & MacOS setting\n    // https://webkit.org/blog/7551/responsive-design-for-motion/\n    reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches\n  };\n\n  // ==========================================================================\n  // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md\n  // https://www.youtube.com/watch?v=NPM6172J22g\n\n  const supportsPassiveListeners = (() => {\n    // Test via a getter in the options object to see if the passive property is accessed\n    let supported = false;\n\n    try {\n      const options = Object.defineProperty({}, 'passive', {\n        get() {\n          supported = true;\n          return null;\n        }\n\n      });\n      window.addEventListener('test', null, options);\n      window.removeEventListener('test', null, options);\n    } catch (_) {// Do nothing\n    }\n\n    return supported;\n  })(); // Toggle event listener\n\n\n  function toggleListener(element, event, callback, toggle = false, passive = true, capture = false) {\n    // Bail if no element, event, or callback\n    if (!element || !('addEventListener' in element) || is.empty(event) || !is.function(callback)) {\n      return;\n    } // Allow multiple events\n\n\n    const events = event.split(' '); // Build options\n    // Default to just the capture boolean for browsers with no passive listener support\n\n    let options = capture; // If passive events listeners are supported\n\n    if (supportsPassiveListeners) {\n      options = {\n        // Whether the listener can be passive (i.e. default never prevented)\n        passive,\n        // Whether the listener is a capturing listener or not\n        capture\n      };\n    } // If a single node is passed, bind the event listener\n\n\n    events.forEach(type => {\n      if (this && this.eventListeners && toggle) {\n        // Cache event listener\n        this.eventListeners.push({\n          element,\n          type,\n          callback,\n          options\n        });\n      }\n\n      element[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options);\n    });\n  } // Bind event handler\n\n  function on(element, events = '', callback, passive = true, capture = false) {\n    toggleListener.call(this, element, events, callback, true, passive, capture);\n  } // Unbind event handler\n\n  function off(element, events = '', callback, passive = true, capture = false) {\n    toggleListener.call(this, element, events, callback, false, passive, capture);\n  } // Bind once-only event handler\n\n  function once(element, events = '', callback, passive = true, capture = false) {\n    const onceCallback = (...args) => {\n      off(element, events, onceCallback, passive, capture);\n      callback.apply(this, args);\n    };\n\n    toggleListener.call(this, element, events, onceCallback, true, passive, capture);\n  } // Trigger event\n\n  function triggerEvent(element, type = '', bubbles = false, detail = {}) {\n    // Bail if no element\n    if (!is.element(element) || is.empty(type)) {\n      return;\n    } // Create and dispatch the event\n\n\n    const event = new CustomEvent(type, {\n      bubbles,\n      detail: { ...detail,\n        plyr: this\n      }\n    }); // Dispatch the event\n\n    element.dispatchEvent(event);\n  } // Unbind all cached event listeners\n\n  function unbindListeners() {\n    if (this && this.eventListeners) {\n      this.eventListeners.forEach(item => {\n        const {\n          element,\n          type,\n          callback,\n          options\n        } = item;\n        element.removeEventListener(type, callback, options);\n      });\n      this.eventListeners = [];\n    }\n  } // Run method when / if player is ready\n\n  function ready() {\n    return new Promise(resolve => this.ready ? setTimeout(resolve, 0) : on.call(this, this.elements.container, 'ready', resolve)).then(() => {});\n  }\n\n  /**\n   * Silence a Promise-like object.\n   * This is useful for avoiding non-harmful, but potentially confusing \"uncaught\n   * play promise\" rejection error messages.\n   * @param  {Object} value An object that may or may not be `Promise`-like.\n   */\n\n  function silencePromise(value) {\n    if (is.promise(value)) {\n      value.then(null, () => {});\n    }\n  }\n\n  // ==========================================================================\n\n  function dedupe(array) {\n    if (!is.array(array)) {\n      return array;\n    }\n\n    return array.filter((item, index) => array.indexOf(item) === index);\n  } // Get the closest value in an array\n\n  function closest(array, value) {\n    if (!is.array(array) || !array.length) {\n      return null;\n    }\n\n    return array.reduce((prev, curr) => Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev);\n  }\n\n  // ==========================================================================\n\n  function supportsCSS(declaration) {\n    if (!window || !window.CSS) {\n      return false;\n    }\n\n    return window.CSS.supports(declaration);\n  } // Standard/common aspect ratios\n\n  const standardRatios = [[1, 1], [4, 3], [3, 4], [5, 4], [4, 5], [3, 2], [2, 3], [16, 10], [10, 16], [16, 9], [9, 16], [21, 9], [9, 21], [32, 9], [9, 32]].reduce((out, [x, y]) => ({ ...out,\n    [x / y]: [x, y]\n  }), {}); // Validate an aspect ratio\n\n  function validateAspectRatio(input) {\n    if (!is.array(input) && (!is.string(input) || !input.includes(':'))) {\n      return false;\n    }\n\n    const ratio = is.array(input) ? input : input.split(':');\n    return ratio.map(Number).every(is.number);\n  } // Reduce an aspect ratio to it's lowest form\n\n  function reduceAspectRatio(ratio) {\n    if (!is.array(ratio) || !ratio.every(is.number)) {\n      return null;\n    }\n\n    const [width, height] = ratio;\n\n    const getDivider = (w, h) => h === 0 ? w : getDivider(h, w % h);\n\n    const divider = getDivider(width, height);\n    return [width / divider, height / divider];\n  } // Calculate an aspect ratio\n\n  function getAspectRatio(input) {\n    const parse = ratio => validateAspectRatio(ratio) ? ratio.split(':').map(Number) : null; // Try provided ratio\n\n\n    let ratio = parse(input); // Get from config\n\n    if (ratio === null) {\n      ratio = parse(this.config.ratio);\n    } // Get from embed\n\n\n    if (ratio === null && !is.empty(this.embed) && is.array(this.embed.ratio)) {\n      ({\n        ratio\n      } = this.embed);\n    } // Get from HTML5 video\n\n\n    if (ratio === null && this.isHTML5) {\n      const {\n        videoWidth,\n        videoHeight\n      } = this.media;\n      ratio = [videoWidth, videoHeight];\n    }\n\n    return reduceAspectRatio(ratio);\n  } // Set aspect ratio for responsive container\n\n  function setAspectRatio(input) {\n    if (!this.isVideo) {\n      return {};\n    }\n\n    const {\n      wrapper\n    } = this.elements;\n    const ratio = getAspectRatio.call(this, input);\n\n    if (!is.array(ratio)) {\n      return {};\n    }\n\n    const [x, y] = reduceAspectRatio(ratio);\n    const useNative = supportsCSS(`aspect-ratio: ${x}/${y}`);\n    const padding = 100 / x * y;\n\n    if (useNative) {\n      wrapper.style.aspectRatio = `${x}/${y}`;\n    } else {\n      wrapper.style.paddingBottom = `${padding}%`;\n    } // For Vimeo we have an extra <div> to hide the standard controls and UI\n\n\n    if (this.isVimeo && !this.config.vimeo.premium && this.supported.ui) {\n      const height = 100 / this.media.offsetWidth * parseInt(window.getComputedStyle(this.media).paddingBottom, 10);\n      const offset = (height - padding) / (height / 50);\n\n      if (this.fullscreen.active) {\n        wrapper.style.paddingBottom = null;\n      } else {\n        this.media.style.transform = `translateY(-${offset}%)`;\n      }\n    } else if (this.isHTML5) {\n      wrapper.classList.add(this.config.classNames.videoFixedRatio);\n    }\n\n    return {\n      padding,\n      ratio\n    };\n  } // Round an aspect ratio to closest standard ratio\n\n  function roundAspectRatio(x, y, tolerance = 0.05) {\n    const ratio = x / y;\n    const closestRatio = closest(Object.keys(standardRatios), ratio); // Check match is within tolerance\n\n    if (Math.abs(closestRatio - ratio) <= tolerance) {\n      return standardRatios[closestRatio];\n    } // No match\n\n\n    return [x, y];\n  } // Get the size of the viewport\n  // https://stackoverflow.com/questions/1248081/how-to-get-the-browser-viewport-dimensions\n\n  function getViewportSize() {\n    const width = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);\n    const height = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0);\n    return [width, height];\n  }\n\n  // ==========================================================================\n  const html5 = {\n    getSources() {\n      if (!this.isHTML5) {\n        return [];\n      }\n\n      const sources = Array.from(this.media.querySelectorAll('source')); // Filter out unsupported sources (if type is specified)\n\n      return sources.filter(source => {\n        const type = source.getAttribute('type');\n\n        if (is.empty(type)) {\n          return true;\n        }\n\n        return support.mime.call(this, type);\n      });\n    },\n\n    // Get quality levels\n    getQualityOptions() {\n      // Whether we're forcing all options (e.g. for streaming)\n      if (this.config.quality.forced) {\n        return this.config.quality.options;\n      } // Get sizes from <source> elements\n\n\n      return html5.getSources.call(this).map(source => Number(source.getAttribute('size'))).filter(Boolean);\n    },\n\n    setup() {\n      if (!this.isHTML5) {\n        return;\n      }\n\n      const player = this; // Set speed options from config\n\n      player.options.speed = player.config.speed.options; // Set aspect ratio if fixed\n\n      if (!is.empty(this.config.ratio)) {\n        setAspectRatio.call(player);\n      } // Quality\n\n\n      Object.defineProperty(player.media, 'quality', {\n        get() {\n          // Get sources\n          const sources = html5.getSources.call(player);\n          const source = sources.find(s => s.getAttribute('src') === player.source); // Return size, if match is found\n\n          return source && Number(source.getAttribute('size'));\n        },\n\n        set(input) {\n          if (player.quality === input) {\n            return;\n          } // If we're using an external handler...\n\n\n          if (player.config.quality.forced && is.function(player.config.quality.onChange)) {\n            player.config.quality.onChange(input);\n          } else {\n            // Get sources\n            const sources = html5.getSources.call(player); // Get first match for requested size\n\n            const source = sources.find(s => Number(s.getAttribute('size')) === input); // No matching source found\n\n            if (!source) {\n              return;\n            } // Get current state\n\n\n            const {\n              currentTime,\n              paused,\n              preload,\n              readyState,\n              playbackRate\n            } = player.media; // Set new source\n\n            player.media.src = source.getAttribute('src'); // Prevent loading if preload=\"none\" and the current source isn't loaded (#1044)\n\n            if (preload !== 'none' || readyState) {\n              // Restore time\n              player.once('loadedmetadata', () => {\n                player.speed = playbackRate;\n                player.currentTime = currentTime; // Resume playing\n\n                if (!paused) {\n                  silencePromise(player.play());\n                }\n              }); // Load new source\n\n              player.media.load();\n            }\n          } // Trigger change event\n\n\n          triggerEvent.call(player, player.media, 'qualitychange', false, {\n            quality: input\n          });\n        }\n\n      });\n    },\n\n    // Cancel current network requests\n    // See https://github.com/sampotts/plyr/issues/174\n    cancelRequests() {\n      if (!this.isHTML5) {\n        return;\n      } // Remove child sources\n\n\n      removeElement(html5.getSources.call(this)); // Set blank video src attribute\n      // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error\n      // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection\n\n      this.media.setAttribute('src', this.config.blankVideo); // Load the new empty source\n      // This will cancel existing requests\n      // See https://github.com/sampotts/plyr/issues/174\n\n      this.media.load(); // Debugging\n\n      this.debug.log('Cancelled network requests');\n    }\n\n  };\n\n  // ==========================================================================\n\n  function generateId(prefix) {\n    return `${prefix}-${Math.floor(Math.random() * 10000)}`;\n  } // Format string\n\n  function format(input, ...args) {\n    if (is.empty(input)) {\n      return input;\n    }\n\n    return input.toString().replace(/{(\\d+)}/g, (match, i) => args[i].toString());\n  } // Get percentage\n\n  function getPercentage(current, max) {\n    if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) {\n      return 0;\n    }\n\n    return (current / max * 100).toFixed(2);\n  } // Replace all occurances of a string in a string\n\n  const replaceAll = (input = '', find = '', replace = '') => input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\\]/\\\\])/g, '\\\\$1'), 'g'), replace.toString()); // Convert to title case\n\n  const toTitleCase = (input = '') => input.toString().replace(/\\w\\S*/g, text => text.charAt(0).toUpperCase() + text.substr(1).toLowerCase()); // Convert string to pascalCase\n\n  function toPascalCase(input = '') {\n    let string = input.toString(); // Convert kebab case\n\n    string = replaceAll(string, '-', ' '); // Convert snake case\n\n    string = replaceAll(string, '_', ' '); // Convert to title case\n\n    string = toTitleCase(string); // Convert to pascal case\n\n    return replaceAll(string, ' ', '');\n  } // Convert string to pascalCase\n\n  function toCamelCase(input = '') {\n    let string = input.toString(); // Convert to pascal case\n\n    string = toPascalCase(string); // Convert first character to lowercase\n\n    return string.charAt(0).toLowerCase() + string.slice(1);\n  } // Remove HTML from a string\n\n  function stripHTML(source) {\n    const fragment = document.createDocumentFragment();\n    const element = document.createElement('div');\n    fragment.appendChild(element);\n    element.innerHTML = source;\n    return fragment.firstChild.innerText;\n  } // Like outerHTML, but also works for DocumentFragment\n\n  function getHTML(element) {\n    const wrapper = document.createElement('div');\n    wrapper.appendChild(element);\n    return wrapper.innerHTML;\n  }\n\n  // ==========================================================================\n\n  const resources = {\n    pip: 'PIP',\n    airplay: 'AirPlay',\n    html5: 'HTML5',\n    vimeo: 'Vimeo',\n    youtube: 'YouTube'\n  };\n  const i18n = {\n    get(key = '', config = {}) {\n      if (is.empty(key) || is.empty(config)) {\n        return '';\n      }\n\n      let string = getDeep(config.i18n, key);\n\n      if (is.empty(string)) {\n        if (Object.keys(resources).includes(key)) {\n          return resources[key];\n        }\n\n        return '';\n      }\n\n      const replace = {\n        '{seektime}': config.seekTime,\n        '{title}': config.title\n      };\n      Object.entries(replace).forEach(([k, v]) => {\n        string = replaceAll(string, k, v);\n      });\n      return string;\n    }\n\n  };\n\n  class Storage {\n    constructor(player) {\n      _defineProperty$1(this, \"get\", key => {\n        if (!Storage.supported || !this.enabled) {\n          return null;\n        }\n\n        const store = window.localStorage.getItem(this.key);\n\n        if (is.empty(store)) {\n          return null;\n        }\n\n        const json = JSON.parse(store);\n        return is.string(key) && key.length ? json[key] : json;\n      });\n\n      _defineProperty$1(this, \"set\", object => {\n        // Bail if we don't have localStorage support or it's disabled\n        if (!Storage.supported || !this.enabled) {\n          return;\n        } // Can only store objectst\n\n\n        if (!is.object(object)) {\n          return;\n        } // Get current storage\n\n\n        let storage = this.get(); // Default to empty object\n\n        if (is.empty(storage)) {\n          storage = {};\n        } // Update the working copy of the values\n\n\n        extend(storage, object); // Update storage\n\n        try {\n          window.localStorage.setItem(this.key, JSON.stringify(storage));\n        } catch (_) {// Do nothing\n        }\n      });\n\n      this.enabled = player.config.storage.enabled;\n      this.key = player.config.storage.key;\n    } // Check for actual support (see if we can use it)\n\n\n    static get supported() {\n      try {\n        if (!('localStorage' in window)) {\n          return false;\n        }\n\n        const test = '___test'; // Try to use it (it might be disabled, e.g. user is in private mode)\n        // see: https://github.com/sampotts/plyr/issues/131\n\n        window.localStorage.setItem(test, test);\n        window.localStorage.removeItem(test);\n        return true;\n      } catch (_) {\n        return false;\n      }\n    }\n\n  }\n\n  // ==========================================================================\n  // Fetch wrapper\n  // Using XHR to avoid issues with older browsers\n  // ==========================================================================\n  function fetch(url, responseType = 'text') {\n    return new Promise((resolve, reject) => {\n      try {\n        const request = new XMLHttpRequest(); // Check for CORS support\n\n        if (!('withCredentials' in request)) {\n          return;\n        }\n\n        request.addEventListener('load', () => {\n          if (responseType === 'text') {\n            try {\n              resolve(JSON.parse(request.responseText));\n            } catch (_) {\n              resolve(request.responseText);\n            }\n          } else {\n            resolve(request.response);\n          }\n        });\n        request.addEventListener('error', () => {\n          throw new Error(request.status);\n        });\n        request.open('GET', url, true); // Set the required response type\n\n        request.responseType = responseType;\n        request.send();\n      } catch (error) {\n        reject(error);\n      }\n    });\n  }\n\n  // ==========================================================================\n\n  function loadSprite(url, id) {\n    if (!is.string(url)) {\n      return;\n    }\n\n    const prefix = 'cache';\n    const hasId = is.string(id);\n    let isCached = false;\n\n    const exists = () => document.getElementById(id) !== null;\n\n    const update = (container, data) => {\n      // eslint-disable-next-line no-param-reassign\n      container.innerHTML = data; // Check again incase of race condition\n\n      if (hasId && exists()) {\n        return;\n      } // Inject the SVG to the body\n\n\n      document.body.insertAdjacentElement('afterbegin', container);\n    }; // Only load once if ID set\n\n\n    if (!hasId || !exists()) {\n      const useStorage = Storage.supported; // Create container\n\n      const container = document.createElement('div');\n      container.setAttribute('hidden', '');\n\n      if (hasId) {\n        container.setAttribute('id', id);\n      } // Check in cache\n\n\n      if (useStorage) {\n        const cached = window.localStorage.getItem(`${prefix}-${id}`);\n        isCached = cached !== null;\n\n        if (isCached) {\n          const data = JSON.parse(cached);\n          update(container, data.content);\n        }\n      } // Get the sprite\n\n\n      fetch(url).then(result => {\n        if (is.empty(result)) {\n          return;\n        }\n\n        if (useStorage) {\n          try {\n            window.localStorage.setItem(`${prefix}-${id}`, JSON.stringify({\n              content: result\n            }));\n          } catch (_) {// Do nothing\n          }\n        }\n\n        update(container, result);\n      }).catch(() => {});\n    }\n  }\n\n  // ==========================================================================\n\n  const getHours = value => Math.trunc(value / 60 / 60 % 60, 10);\n  const getMinutes = value => Math.trunc(value / 60 % 60, 10);\n  const getSeconds = value => Math.trunc(value % 60, 10); // Format time to UI friendly string\n\n  function formatTime(time = 0, displayHours = false, inverted = false) {\n    // Bail if the value isn't a number\n    if (!is.number(time)) {\n      return formatTime(undefined, displayHours, inverted);\n    } // Format time component to add leading zero\n\n\n    const format = value => `0${value}`.slice(-2); // Breakdown to hours, mins, secs\n\n\n    let hours = getHours(time);\n    const mins = getMinutes(time);\n    const secs = getSeconds(time); // Do we need to display hours?\n\n    if (displayHours || hours > 0) {\n      hours = `${hours}:`;\n    } else {\n      hours = '';\n    } // Render\n\n\n    return `${inverted && time > 0 ? '-' : ''}${hours}${format(mins)}:${format(secs)}`;\n  }\n\n  // ==========================================================================\n\n  const controls = {\n    // Get icon URL\n    getIconUrl() {\n      const url = new URL(this.config.iconUrl, window.location);\n      const host = window.location.host ? window.location.host : window.top.location.host;\n      const cors = url.host !== host || browser.isIE && !window.svg4everybody;\n      return {\n        url: this.config.iconUrl,\n        cors\n      };\n    },\n\n    // Find the UI controls\n    findElements() {\n      try {\n        this.elements.controls = getElement.call(this, this.config.selectors.controls.wrapper); // Buttons\n\n        this.elements.buttons = {\n          play: getElements.call(this, this.config.selectors.buttons.play),\n          pause: getElement.call(this, this.config.selectors.buttons.pause),\n          restart: getElement.call(this, this.config.selectors.buttons.restart),\n          rewind: getElement.call(this, this.config.selectors.buttons.rewind),\n          fastForward: getElement.call(this, this.config.selectors.buttons.fastForward),\n          mute: getElement.call(this, this.config.selectors.buttons.mute),\n          pip: getElement.call(this, this.config.selectors.buttons.pip),\n          airplay: getElement.call(this, this.config.selectors.buttons.airplay),\n          settings: getElement.call(this, this.config.selectors.buttons.settings),\n          captions: getElement.call(this, this.config.selectors.buttons.captions),\n          fullscreen: getElement.call(this, this.config.selectors.buttons.fullscreen)\n        }; // Progress\n\n        this.elements.progress = getElement.call(this, this.config.selectors.progress); // Inputs\n\n        this.elements.inputs = {\n          seek: getElement.call(this, this.config.selectors.inputs.seek),\n          volume: getElement.call(this, this.config.selectors.inputs.volume)\n        }; // Display\n\n        this.elements.display = {\n          buffer: getElement.call(this, this.config.selectors.display.buffer),\n          currentTime: getElement.call(this, this.config.selectors.display.currentTime),\n          duration: getElement.call(this, this.config.selectors.display.duration)\n        }; // Seek tooltip\n\n        if (is.element(this.elements.progress)) {\n          this.elements.display.seekTooltip = this.elements.progress.querySelector(`.${this.config.classNames.tooltip}`);\n        }\n\n        return true;\n      } catch (error) {\n        // Log it\n        this.debug.warn('It looks like there is a problem with your custom controls HTML', error); // Restore native video controls\n\n        this.toggleNativeControls(true);\n        return false;\n      }\n    },\n\n    // Create <svg> icon\n    createIcon(type, attributes) {\n      const namespace = 'http://www.w3.org/2000/svg';\n      const iconUrl = controls.getIconUrl.call(this);\n      const iconPath = `${!iconUrl.cors ? iconUrl.url : ''}#${this.config.iconPrefix}`; // Create <svg>\n\n      const icon = document.createElementNS(namespace, 'svg');\n      setAttributes(icon, extend(attributes, {\n        'aria-hidden': 'true',\n        focusable: 'false'\n      })); // Create the <use> to reference sprite\n\n      const use = document.createElementNS(namespace, 'use');\n      const path = `${iconPath}-${type}`; // Set `href` attributes\n      // https://github.com/sampotts/plyr/issues/460\n      // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href\n\n      if ('href' in use) {\n        use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path);\n      } // Always set the older attribute even though it's \"deprecated\" (it'll be around for ages)\n\n\n      use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path); // Add <use> to <svg>\n\n      icon.appendChild(use);\n      return icon;\n    },\n\n    // Create hidden text label\n    createLabel(key, attr = {}) {\n      const text = i18n.get(key, this.config);\n      const attributes = { ...attr,\n        class: [attr.class, this.config.classNames.hidden].filter(Boolean).join(' ')\n      };\n      return createElement('span', attributes, text);\n    },\n\n    // Create a badge\n    createBadge(text) {\n      if (is.empty(text)) {\n        return null;\n      }\n\n      const badge = createElement('span', {\n        class: this.config.classNames.menu.value\n      });\n      badge.appendChild(createElement('span', {\n        class: this.config.classNames.menu.badge\n      }, text));\n      return badge;\n    },\n\n    // Create a <button>\n    createButton(buttonType, attr) {\n      const attributes = extend({}, attr);\n      let type = toCamelCase(buttonType);\n      const props = {\n        element: 'button',\n        toggle: false,\n        label: null,\n        icon: null,\n        labelPressed: null,\n        iconPressed: null\n      };\n      ['element', 'icon', 'label'].forEach(key => {\n        if (Object.keys(attributes).includes(key)) {\n          props[key] = attributes[key];\n          delete attributes[key];\n        }\n      }); // Default to 'button' type to prevent form submission\n\n      if (props.element === 'button' && !Object.keys(attributes).includes('type')) {\n        attributes.type = 'button';\n      } // Set class name\n\n\n      if (Object.keys(attributes).includes('class')) {\n        if (!attributes.class.split(' ').some(c => c === this.config.classNames.control)) {\n          extend(attributes, {\n            class: `${attributes.class} ${this.config.classNames.control}`\n          });\n        }\n      } else {\n        attributes.class = this.config.classNames.control;\n      } // Large play button\n\n\n      switch (buttonType) {\n        case 'play':\n          props.toggle = true;\n          props.label = 'play';\n          props.labelPressed = 'pause';\n          props.icon = 'play';\n          props.iconPressed = 'pause';\n          break;\n\n        case 'mute':\n          props.toggle = true;\n          props.label = 'mute';\n          props.labelPressed = 'unmute';\n          props.icon = 'volume';\n          props.iconPressed = 'muted';\n          break;\n\n        case 'captions':\n          props.toggle = true;\n          props.label = 'enableCaptions';\n          props.labelPressed = 'disableCaptions';\n          props.icon = 'captions-off';\n          props.iconPressed = 'captions-on';\n          break;\n\n        case 'fullscreen':\n          props.toggle = true;\n          props.label = 'enterFullscreen';\n          props.labelPressed = 'exitFullscreen';\n          props.icon = 'enter-fullscreen';\n          props.iconPressed = 'exit-fullscreen';\n          break;\n\n        case 'play-large':\n          attributes.class += ` ${this.config.classNames.control}--overlaid`;\n          type = 'play';\n          props.label = 'play';\n          props.icon = 'play';\n          break;\n\n        default:\n          if (is.empty(props.label)) {\n            props.label = type;\n          }\n\n          if (is.empty(props.icon)) {\n            props.icon = buttonType;\n          }\n\n      }\n\n      const button = createElement(props.element); // Setup toggle icon and labels\n\n      if (props.toggle) {\n        // Icon\n        button.appendChild(controls.createIcon.call(this, props.iconPressed, {\n          class: 'icon--pressed'\n        }));\n        button.appendChild(controls.createIcon.call(this, props.icon, {\n          class: 'icon--not-pressed'\n        })); // Label/Tooltip\n\n        button.appendChild(controls.createLabel.call(this, props.labelPressed, {\n          class: 'label--pressed'\n        }));\n        button.appendChild(controls.createLabel.call(this, props.label, {\n          class: 'label--not-pressed'\n        }));\n      } else {\n        button.appendChild(controls.createIcon.call(this, props.icon));\n        button.appendChild(controls.createLabel.call(this, props.label));\n      } // Merge and set attributes\n\n\n      extend(attributes, getAttributesFromSelector(this.config.selectors.buttons[type], attributes));\n      setAttributes(button, attributes); // We have multiple play buttons\n\n      if (type === 'play') {\n        if (!is.array(this.elements.buttons[type])) {\n          this.elements.buttons[type] = [];\n        }\n\n        this.elements.buttons[type].push(button);\n      } else {\n        this.elements.buttons[type] = button;\n      }\n\n      return button;\n    },\n\n    // Create an <input type='range'>\n    createRange(type, attributes) {\n      // Seek input\n      const input = createElement('input', extend(getAttributesFromSelector(this.config.selectors.inputs[type]), {\n        type: 'range',\n        min: 0,\n        max: 100,\n        step: 0.01,\n        value: 0,\n        autocomplete: 'off',\n        // A11y fixes for https://github.com/sampotts/plyr/issues/905\n        role: 'slider',\n        'aria-label': i18n.get(type, this.config),\n        'aria-valuemin': 0,\n        'aria-valuemax': 100,\n        'aria-valuenow': 0\n      }, attributes));\n      this.elements.inputs[type] = input; // Set the fill for webkit now\n\n      controls.updateRangeFill.call(this, input); // Improve support on touch devices\n\n      RangeTouch.setup(input);\n      return input;\n    },\n\n    // Create a <progress>\n    createProgress(type, attributes) {\n      const progress = createElement('progress', extend(getAttributesFromSelector(this.config.selectors.display[type]), {\n        min: 0,\n        max: 100,\n        value: 0,\n        role: 'progressbar',\n        'aria-hidden': true\n      }, attributes)); // Create the label inside\n\n      if (type !== 'volume') {\n        progress.appendChild(createElement('span', null, '0'));\n        const suffixKey = {\n          played: 'played',\n          buffer: 'buffered'\n        }[type];\n        const suffix = suffixKey ? i18n.get(suffixKey, this.config) : '';\n        progress.innerText = `% ${suffix.toLowerCase()}`;\n      }\n\n      this.elements.display[type] = progress;\n      return progress;\n    },\n\n    // Create time display\n    createTime(type, attrs) {\n      const attributes = getAttributesFromSelector(this.config.selectors.display[type], attrs);\n      const container = createElement('div', extend(attributes, {\n        class: `${attributes.class ? attributes.class : ''} ${this.config.classNames.display.time} `.trim(),\n        'aria-label': i18n.get(type, this.config)\n      }), '00:00'); // Reference for updates\n\n      this.elements.display[type] = container;\n      return container;\n    },\n\n    // Bind keyboard shortcuts for a menu item\n    // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus\n    // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143\n    bindMenuItemShortcuts(menuItem, type) {\n      // Navigate through menus via arrow keys and space\n      on.call(this, menuItem, 'keydown keyup', event => {\n        // We only care about space and \u2B06\uFE0F \u2B07\uFE0F\uFE0F \u27A1\uFE0F\n        if (![32, 38, 39, 40].includes(event.which)) {\n          return;\n        } // Prevent play / seek\n\n\n        event.preventDefault();\n        event.stopPropagation(); // We're just here to prevent the keydown bubbling\n\n        if (event.type === 'keydown') {\n          return;\n        }\n\n        const isRadioButton = matches(menuItem, '[role=\"menuitemradio\"]'); // Show the respective menu\n\n        if (!isRadioButton && [32, 39].includes(event.which)) {\n          controls.showMenuPanel.call(this, type, true);\n        } else {\n          let target;\n\n          if (event.which !== 32) {\n            if (event.which === 40 || isRadioButton && event.which === 39) {\n              target = menuItem.nextElementSibling;\n\n              if (!is.element(target)) {\n                target = menuItem.parentNode.firstElementChild;\n              }\n            } else {\n              target = menuItem.previousElementSibling;\n\n              if (!is.element(target)) {\n                target = menuItem.parentNode.lastElementChild;\n              }\n            }\n\n            setFocus.call(this, target, true);\n          }\n        }\n      }, false); // Enter will fire a `click` event but we still need to manage focus\n      // So we bind to keyup which fires after and set focus here\n\n      on.call(this, menuItem, 'keyup', event => {\n        if (event.which !== 13) {\n          return;\n        }\n\n        controls.focusFirstMenuItem.call(this, null, true);\n      });\n    },\n\n    // Create a settings menu item\n    createMenuItem({\n      value,\n      list,\n      type,\n      title,\n      badge = null,\n      checked = false\n    }) {\n      const attributes = getAttributesFromSelector(this.config.selectors.inputs[type]);\n      const menuItem = createElement('button', extend(attributes, {\n        type: 'button',\n        role: 'menuitemradio',\n        class: `${this.config.classNames.control} ${attributes.class ? attributes.class : ''}`.trim(),\n        'aria-checked': checked,\n        value\n      }));\n      const flex = createElement('span'); // We have to set as HTML incase of special characters\n\n      flex.innerHTML = title;\n\n      if (is.element(badge)) {\n        flex.appendChild(badge);\n      }\n\n      menuItem.appendChild(flex); // Replicate radio button behaviour\n\n      Object.defineProperty(menuItem, 'checked', {\n        enumerable: true,\n\n        get() {\n          return menuItem.getAttribute('aria-checked') === 'true';\n        },\n\n        set(check) {\n          // Ensure exclusivity\n          if (check) {\n            Array.from(menuItem.parentNode.children).filter(node => matches(node, '[role=\"menuitemradio\"]')).forEach(node => node.setAttribute('aria-checked', 'false'));\n          }\n\n          menuItem.setAttribute('aria-checked', check ? 'true' : 'false');\n        }\n\n      });\n      this.listeners.bind(menuItem, 'click keyup', event => {\n        if (is.keyboardEvent(event) && event.which !== 32) {\n          return;\n        }\n\n        event.preventDefault();\n        event.stopPropagation();\n        menuItem.checked = true;\n\n        switch (type) {\n          case 'language':\n            this.currentTrack = Number(value);\n            break;\n\n          case 'quality':\n            this.quality = value;\n            break;\n\n          case 'speed':\n            this.speed = parseFloat(value);\n            break;\n        }\n\n        controls.showMenuPanel.call(this, 'home', is.keyboardEvent(event));\n      }, type, false);\n      controls.bindMenuItemShortcuts.call(this, menuItem, type);\n      list.appendChild(menuItem);\n    },\n\n    // Format a time for display\n    formatTime(time = 0, inverted = false) {\n      // Bail if the value isn't a number\n      if (!is.number(time)) {\n        return time;\n      } // Always display hours if duration is over an hour\n\n\n      const forceHours = getHours(this.duration) > 0;\n      return formatTime(time, forceHours, inverted);\n    },\n\n    // Update the displayed time\n    updateTimeDisplay(target = null, time = 0, inverted = false) {\n      // Bail if there's no element to display or the value isn't a number\n      if (!is.element(target) || !is.number(time)) {\n        return;\n      } // eslint-disable-next-line no-param-reassign\n\n\n      target.innerText = controls.formatTime(time, inverted);\n    },\n\n    // Update volume UI and storage\n    updateVolume() {\n      if (!this.supported.ui) {\n        return;\n      } // Update range\n\n\n      if (is.element(this.elements.inputs.volume)) {\n        controls.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume);\n      } // Update mute state\n\n\n      if (is.element(this.elements.buttons.mute)) {\n        this.elements.buttons.mute.pressed = this.muted || this.volume === 0;\n      }\n    },\n\n    // Update seek value and lower fill\n    setRange(target, value = 0) {\n      if (!is.element(target)) {\n        return;\n      } // eslint-disable-next-line\n\n\n      target.value = value; // Webkit range fill\n\n      controls.updateRangeFill.call(this, target);\n    },\n\n    // Update <progress> elements\n    updateProgress(event) {\n      if (!this.supported.ui || !is.event(event)) {\n        return;\n      }\n\n      let value = 0;\n\n      const setProgress = (target, input) => {\n        const val = is.number(input) ? input : 0;\n        const progress = is.element(target) ? target : this.elements.display.buffer; // Update value and label\n\n        if (is.element(progress)) {\n          progress.value = val; // Update text label inside\n\n          const label = progress.getElementsByTagName('span')[0];\n\n          if (is.element(label)) {\n            label.childNodes[0].nodeValue = val;\n          }\n        }\n      };\n\n      if (event) {\n        switch (event.type) {\n          // Video playing\n          case 'timeupdate':\n          case 'seeking':\n          case 'seeked':\n            value = getPercentage(this.currentTime, this.duration); // Set seek range value only if it's a 'natural' time event\n\n            if (event.type === 'timeupdate') {\n              controls.setRange.call(this, this.elements.inputs.seek, value);\n            }\n\n            break;\n          // Check buffer status\n\n          case 'playing':\n          case 'progress':\n            setProgress(this.elements.display.buffer, this.buffered * 100);\n            break;\n        }\n      }\n    },\n\n    // Webkit polyfill for lower fill range\n    updateRangeFill(target) {\n      // Get range from event if event passed\n      const range = is.event(target) ? target.target : target; // Needs to be a valid <input type='range'>\n\n      if (!is.element(range) || range.getAttribute('type') !== 'range') {\n        return;\n      } // Set aria values for https://github.com/sampotts/plyr/issues/905\n\n\n      if (matches(range, this.config.selectors.inputs.seek)) {\n        range.setAttribute('aria-valuenow', this.currentTime);\n        const currentTime = controls.formatTime(this.currentTime);\n        const duration = controls.formatTime(this.duration);\n        const format = i18n.get('seekLabel', this.config);\n        range.setAttribute('aria-valuetext', format.replace('{currentTime}', currentTime).replace('{duration}', duration));\n      } else if (matches(range, this.config.selectors.inputs.volume)) {\n        const percent = range.value * 100;\n        range.setAttribute('aria-valuenow', percent);\n        range.setAttribute('aria-valuetext', `${percent.toFixed(1)}%`);\n      } else {\n        range.setAttribute('aria-valuenow', range.value);\n      } // WebKit only\n\n\n      if (!browser.isWebkit) {\n        return;\n      } // Set CSS custom property\n\n\n      range.style.setProperty('--value', `${range.value / range.max * 100}%`);\n    },\n\n    // Update hover tooltip for seeking\n    updateSeekTooltip(event) {\n      // Bail if setting not true\n      if (!this.config.tooltips.seek || !is.element(this.elements.inputs.seek) || !is.element(this.elements.display.seekTooltip) || this.duration === 0) {\n        return;\n      }\n\n      const visible = `${this.config.classNames.tooltip}--visible`;\n\n      const toggle = show => toggleClass(this.elements.display.seekTooltip, visible, show); // Hide on touch\n\n\n      if (this.touch) {\n        toggle(false);\n        return;\n      } // Determine percentage, if already visible\n\n\n      let percent = 0;\n      const clientRect = this.elements.progress.getBoundingClientRect();\n\n      if (is.event(event)) {\n        percent = 100 / clientRect.width * (event.pageX - clientRect.left);\n      } else if (hasClass(this.elements.display.seekTooltip, visible)) {\n        percent = parseFloat(this.elements.display.seekTooltip.style.left, 10);\n      } else {\n        return;\n      } // Set bounds\n\n\n      if (percent < 0) {\n        percent = 0;\n      } else if (percent > 100) {\n        percent = 100;\n      } // Display the time a click would seek to\n\n\n      controls.updateTimeDisplay.call(this, this.elements.display.seekTooltip, this.duration / 100 * percent); // Set position\n\n      this.elements.display.seekTooltip.style.left = `${percent}%`; // Show/hide the tooltip\n      // If the event is a moues in/out and percentage is inside bounds\n\n      if (is.event(event) && ['mouseenter', 'mouseleave'].includes(event.type)) {\n        toggle(event.type === 'mouseenter');\n      }\n    },\n\n    // Handle time change event\n    timeUpdate(event) {\n      // Only invert if only one time element is displayed and used for both duration and currentTime\n      const invert = !is.element(this.elements.display.duration) && this.config.invertTime; // Duration\n\n      controls.updateTimeDisplay.call(this, this.elements.display.currentTime, invert ? this.duration - this.currentTime : this.currentTime, invert); // Ignore updates while seeking\n\n      if (event && event.type === 'timeupdate' && this.media.seeking) {\n        return;\n      } // Playing progress\n\n\n      controls.updateProgress.call(this, event);\n    },\n\n    // Show the duration on metadataloaded or durationchange events\n    durationUpdate() {\n      // Bail if no UI or durationchange event triggered after playing/seek when invertTime is false\n      if (!this.supported.ui || !this.config.invertTime && this.currentTime) {\n        return;\n      } // If duration is the 2**32 (shaka), Infinity (HLS), DASH-IF (Number.MAX_SAFE_INTEGER || Number.MAX_VALUE) indicating live we hide the currentTime and progressbar.\n      // https://github.com/video-dev/hls.js/blob/5820d29d3c4c8a46e8b75f1e3afa3e68c1a9a2db/src/controller/buffer-controller.js#L415\n      // https://github.com/google/shaka-player/blob/4d889054631f4e1cf0fbd80ddd2b71887c02e232/lib/media/streaming_engine.js#L1062\n      // https://github.com/Dash-Industry-Forum/dash.js/blob/69859f51b969645b234666800d4cb596d89c602d/src/dash/models/DashManifestModel.js#L338\n\n\n      if (this.duration >= 2 ** 32) {\n        toggleHidden(this.elements.display.currentTime, true);\n        toggleHidden(this.elements.progress, true);\n        return;\n      } // Update ARIA values\n\n\n      if (is.element(this.elements.inputs.seek)) {\n        this.elements.inputs.seek.setAttribute('aria-valuemax', this.duration);\n      } // If there's a spot to display duration\n\n\n      const hasDuration = is.element(this.elements.display.duration); // If there's only one time display, display duration there\n\n      if (!hasDuration && this.config.displayDuration && this.paused) {\n        controls.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration);\n      } // If there's a duration element, update content\n\n\n      if (hasDuration) {\n        controls.updateTimeDisplay.call(this, this.elements.display.duration, this.duration);\n      } // Update the tooltip (if visible)\n\n\n      controls.updateSeekTooltip.call(this);\n    },\n\n    // Hide/show a tab\n    toggleMenuButton(setting, toggle) {\n      toggleHidden(this.elements.settings.buttons[setting], !toggle);\n    },\n\n    // Update the selected setting\n    updateSetting(setting, container, input) {\n      const pane = this.elements.settings.panels[setting];\n      let value = null;\n      let list = container;\n\n      if (setting === 'captions') {\n        value = this.currentTrack;\n      } else {\n        value = !is.empty(input) ? input : this[setting]; // Get default\n\n        if (is.empty(value)) {\n          value = this.config[setting].default;\n        } // Unsupported value\n\n\n        if (!is.empty(this.options[setting]) && !this.options[setting].includes(value)) {\n          this.debug.warn(`Unsupported value of '${value}' for ${setting}`);\n          return;\n        } // Disabled value\n\n\n        if (!this.config[setting].options.includes(value)) {\n          this.debug.warn(`Disabled value of '${value}' for ${setting}`);\n          return;\n        }\n      } // Get the list if we need to\n\n\n      if (!is.element(list)) {\n        list = pane && pane.querySelector('[role=\"menu\"]');\n      } // If there's no list it means it's not been rendered...\n\n\n      if (!is.element(list)) {\n        return;\n      } // Update the label\n\n\n      const label = this.elements.settings.buttons[setting].querySelector(`.${this.config.classNames.menu.value}`);\n      label.innerHTML = controls.getLabel.call(this, setting, value); // Find the radio option and check it\n\n      const target = list && list.querySelector(`[value=\"${value}\"]`);\n\n      if (is.element(target)) {\n        target.checked = true;\n      }\n    },\n\n    // Translate a value into a nice label\n    getLabel(setting, value) {\n      switch (setting) {\n        case 'speed':\n          return value === 1 ? i18n.get('normal', this.config) : `${value}&times;`;\n\n        case 'quality':\n          if (is.number(value)) {\n            const label = i18n.get(`qualityLabel.${value}`, this.config);\n\n            if (!label.length) {\n              return `${value}p`;\n            }\n\n            return label;\n          }\n\n          return toTitleCase(value);\n\n        case 'captions':\n          return captions.getLabel.call(this);\n\n        default:\n          return null;\n      }\n    },\n\n    // Set the quality menu\n    setQualityMenu(options) {\n      // Menu required\n      if (!is.element(this.elements.settings.panels.quality)) {\n        return;\n      }\n\n      const type = 'quality';\n      const list = this.elements.settings.panels.quality.querySelector('[role=\"menu\"]'); // Set options if passed and filter based on uniqueness and config\n\n      if (is.array(options)) {\n        this.options.quality = dedupe(options).filter(quality => this.config.quality.options.includes(quality));\n      } // Toggle the pane and tab\n\n\n      const toggle = !is.empty(this.options.quality) && this.options.quality.length > 1;\n      controls.toggleMenuButton.call(this, type, toggle); // Empty the menu\n\n      emptyElement(list); // Check if we need to toggle the parent\n\n      controls.checkMenu.call(this); // If we're hiding, nothing more to do\n\n      if (!toggle) {\n        return;\n      } // Get the badge HTML for HD, 4K etc\n\n\n      const getBadge = quality => {\n        const label = i18n.get(`qualityBadge.${quality}`, this.config);\n\n        if (!label.length) {\n          return null;\n        }\n\n        return controls.createBadge.call(this, label);\n      }; // Sort options by the config and then render options\n\n\n      this.options.quality.sort((a, b) => {\n        const sorting = this.config.quality.options;\n        return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1;\n      }).forEach(quality => {\n        controls.createMenuItem.call(this, {\n          value: quality,\n          list,\n          type,\n          title: controls.getLabel.call(this, 'quality', quality),\n          badge: getBadge(quality)\n        });\n      });\n      controls.updateSetting.call(this, type, list);\n    },\n\n    // Set the looping options\n\n    /* setLoopMenu() {\n          // Menu required\n          if (!is.element(this.elements.settings.panels.loop)) {\n              return;\n          }\n           const options = ['start', 'end', 'all', 'reset'];\n          const list = this.elements.settings.panels.loop.querySelector('[role=\"menu\"]');\n           // Show the pane and tab\n          toggleHidden(this.elements.settings.buttons.loop, false);\n          toggleHidden(this.elements.settings.panels.loop, false);\n           // Toggle the pane and tab\n          const toggle = !is.empty(this.loop.options);\n          controls.toggleMenuButton.call(this, 'loop', toggle);\n           // Empty the menu\n          emptyElement(list);\n           options.forEach(option => {\n              const item = createElement('li');\n               const button = createElement(\n                  'button',\n                  extend(getAttributesFromSelector(this.config.selectors.buttons.loop), {\n                      type: 'button',\n                      class: this.config.classNames.control,\n                      'data-plyr-loop-action': option,\n                  }),\n                  i18n.get(option, this.config)\n              );\n               if (['start', 'end'].includes(option)) {\n                  const badge = controls.createBadge.call(this, '00:00');\n                  button.appendChild(badge);\n              }\n               item.appendChild(button);\n              list.appendChild(item);\n          });\n      }, */\n    // Get current selected caption language\n    // TODO: rework this to user the getter in the API?\n    // Set a list of available captions languages\n    setCaptionsMenu() {\n      // Menu required\n      if (!is.element(this.elements.settings.panels.captions)) {\n        return;\n      } // TODO: Captions or language? Currently it's mixed\n\n\n      const type = 'captions';\n      const list = this.elements.settings.panels.captions.querySelector('[role=\"menu\"]');\n      const tracks = captions.getTracks.call(this);\n      const toggle = Boolean(tracks.length); // Toggle the pane and tab\n\n      controls.toggleMenuButton.call(this, type, toggle); // Empty the menu\n\n      emptyElement(list); // Check if we need to toggle the parent\n\n      controls.checkMenu.call(this); // If there's no captions, bail\n\n      if (!toggle) {\n        return;\n      } // Generate options data\n\n\n      const options = tracks.map((track, value) => ({\n        value,\n        checked: this.captions.toggled && this.currentTrack === value,\n        title: captions.getLabel.call(this, track),\n        badge: track.language && controls.createBadge.call(this, track.language.toUpperCase()),\n        list,\n        type: 'language'\n      })); // Add the \"Disabled\" option to turn off captions\n\n      options.unshift({\n        value: -1,\n        checked: !this.captions.toggled,\n        title: i18n.get('disabled', this.config),\n        list,\n        type: 'language'\n      }); // Generate options\n\n      options.forEach(controls.createMenuItem.bind(this));\n      controls.updateSetting.call(this, type, list);\n    },\n\n    // Set a list of available captions languages\n    setSpeedMenu() {\n      // Menu required\n      if (!is.element(this.elements.settings.panels.speed)) {\n        return;\n      }\n\n      const type = 'speed';\n      const list = this.elements.settings.panels.speed.querySelector('[role=\"menu\"]'); // Filter out invalid speeds\n\n      this.options.speed = this.options.speed.filter(o => o >= this.minimumSpeed && o <= this.maximumSpeed); // Toggle the pane and tab\n\n      const toggle = !is.empty(this.options.speed) && this.options.speed.length > 1;\n      controls.toggleMenuButton.call(this, type, toggle); // Empty the menu\n\n      emptyElement(list); // Check if we need to toggle the parent\n\n      controls.checkMenu.call(this); // If we're hiding, nothing more to do\n\n      if (!toggle) {\n        return;\n      } // Create items\n\n\n      this.options.speed.forEach(speed => {\n        controls.createMenuItem.call(this, {\n          value: speed,\n          list,\n          type,\n          title: controls.getLabel.call(this, 'speed', speed)\n        });\n      });\n      controls.updateSetting.call(this, type, list);\n    },\n\n    // Check if we need to hide/show the settings menu\n    checkMenu() {\n      const {\n        buttons\n      } = this.elements.settings;\n      const visible = !is.empty(buttons) && Object.values(buttons).some(button => !button.hidden);\n      toggleHidden(this.elements.settings.menu, !visible);\n    },\n\n    // Focus the first menu item in a given (or visible) menu\n    focusFirstMenuItem(pane, tabFocus = false) {\n      if (this.elements.settings.popup.hidden) {\n        return;\n      }\n\n      let target = pane;\n\n      if (!is.element(target)) {\n        target = Object.values(this.elements.settings.panels).find(p => !p.hidden);\n      }\n\n      const firstItem = target.querySelector('[role^=\"menuitem\"]');\n      setFocus.call(this, firstItem, tabFocus);\n    },\n\n    // Show/hide menu\n    toggleMenu(input) {\n      const {\n        popup\n      } = this.elements.settings;\n      const button = this.elements.buttons.settings; // Menu and button are required\n\n      if (!is.element(popup) || !is.element(button)) {\n        return;\n      } // True toggle by default\n\n\n      const {\n        hidden\n      } = popup;\n      let show = hidden;\n\n      if (is.boolean(input)) {\n        show = input;\n      } else if (is.keyboardEvent(input) && input.which === 27) {\n        show = false;\n      } else if (is.event(input)) {\n        // If Plyr is in a shadowDOM, the event target is set to the component, instead of the\n        // Element in the shadowDOM. The path, if available, is complete.\n        const target = is.function(input.composedPath) ? input.composedPath()[0] : input.target;\n        const isMenuItem = popup.contains(target); // If the click was inside the menu or if the click\n        // wasn't the button or menu item and we're trying to\n        // show the menu (a doc click shouldn't show the menu)\n\n        if (isMenuItem || !isMenuItem && input.target !== button && show) {\n          return;\n        }\n      } // Set button attributes\n\n\n      button.setAttribute('aria-expanded', show); // Show the actual popup\n\n      toggleHidden(popup, !show); // Add class hook\n\n      toggleClass(this.elements.container, this.config.classNames.menu.open, show); // Focus the first item if key interaction\n\n      if (show && is.keyboardEvent(input)) {\n        controls.focusFirstMenuItem.call(this, null, true);\n      } else if (!show && !hidden) {\n        // If closing, re-focus the button\n        setFocus.call(this, button, is.keyboardEvent(input));\n      }\n    },\n\n    // Get the natural size of a menu panel\n    getMenuSize(tab) {\n      const clone = tab.cloneNode(true);\n      clone.style.position = 'absolute';\n      clone.style.opacity = 0;\n      clone.removeAttribute('hidden'); // Append to parent so we get the \"real\" size\n\n      tab.parentNode.appendChild(clone); // Get the sizes before we remove\n\n      const width = clone.scrollWidth;\n      const height = clone.scrollHeight; // Remove from the DOM\n\n      removeElement(clone);\n      return {\n        width,\n        height\n      };\n    },\n\n    // Show a panel in the menu\n    showMenuPanel(type = '', tabFocus = false) {\n      const target = this.elements.container.querySelector(`#plyr-settings-${this.id}-${type}`); // Nothing to show, bail\n\n      if (!is.element(target)) {\n        return;\n      } // Hide all other panels\n\n\n      const container = target.parentNode;\n      const current = Array.from(container.children).find(node => !node.hidden); // If we can do fancy animations, we'll animate the height/width\n\n      if (support.transitions && !support.reducedMotion) {\n        // Set the current width as a base\n        container.style.width = `${current.scrollWidth}px`;\n        container.style.height = `${current.scrollHeight}px`; // Get potential sizes\n\n        const size = controls.getMenuSize.call(this, target); // Restore auto height/width\n\n        const restore = event => {\n          // We're only bothered about height and width on the container\n          if (event.target !== container || !['width', 'height'].includes(event.propertyName)) {\n            return;\n          } // Revert back to auto\n\n\n          container.style.width = '';\n          container.style.height = ''; // Only listen once\n\n          off.call(this, container, transitionEndEvent, restore);\n        }; // Listen for the transition finishing and restore auto height/width\n\n\n        on.call(this, container, transitionEndEvent, restore); // Set dimensions to target\n\n        container.style.width = `${size.width}px`;\n        container.style.height = `${size.height}px`;\n      } // Set attributes on current tab\n\n\n      toggleHidden(current, true); // Set attributes on target\n\n      toggleHidden(target, false); // Focus the first item\n\n      controls.focusFirstMenuItem.call(this, target, tabFocus);\n    },\n\n    // Set the download URL\n    setDownloadUrl() {\n      const button = this.elements.buttons.download; // Bail if no button\n\n      if (!is.element(button)) {\n        return;\n      } // Set attribute\n\n\n      button.setAttribute('href', this.download);\n    },\n\n    // Build the default HTML\n    create(data) {\n      const {\n        bindMenuItemShortcuts,\n        createButton,\n        createProgress,\n        createRange,\n        createTime,\n        setQualityMenu,\n        setSpeedMenu,\n        showMenuPanel\n      } = controls;\n      this.elements.controls = null; // Larger overlaid play button\n\n      if (is.array(this.config.controls) && this.config.controls.includes('play-large')) {\n        this.elements.container.appendChild(createButton.call(this, 'play-large'));\n      } // Create the container\n\n\n      const container = createElement('div', getAttributesFromSelector(this.config.selectors.controls.wrapper));\n      this.elements.controls = container; // Default item attributes\n\n      const defaultAttributes = {\n        class: 'plyr__controls__item'\n      }; // Loop through controls in order\n\n      dedupe(is.array(this.config.controls) ? this.config.controls : []).forEach(control => {\n        // Restart button\n        if (control === 'restart') {\n          container.appendChild(createButton.call(this, 'restart', defaultAttributes));\n        } // Rewind button\n\n\n        if (control === 'rewind') {\n          container.appendChild(createButton.call(this, 'rewind', defaultAttributes));\n        } // Play/Pause button\n\n\n        if (control === 'play') {\n          container.appendChild(createButton.call(this, 'play', defaultAttributes));\n        } // Fast forward button\n\n\n        if (control === 'fast-forward') {\n          container.appendChild(createButton.call(this, 'fast-forward', defaultAttributes));\n        } // Progress\n\n\n        if (control === 'progress') {\n          const progressContainer = createElement('div', {\n            class: `${defaultAttributes.class} plyr__progress__container`\n          });\n          const progress = createElement('div', getAttributesFromSelector(this.config.selectors.progress)); // Seek range slider\n\n          progress.appendChild(createRange.call(this, 'seek', {\n            id: `plyr-seek-${data.id}`\n          })); // Buffer progress\n\n          progress.appendChild(createProgress.call(this, 'buffer')); // TODO: Add loop display indicator\n          // Seek tooltip\n\n          if (this.config.tooltips.seek) {\n            const tooltip = createElement('span', {\n              class: this.config.classNames.tooltip\n            }, '00:00');\n            progress.appendChild(tooltip);\n            this.elements.display.seekTooltip = tooltip;\n          }\n\n          this.elements.progress = progress;\n          progressContainer.appendChild(this.elements.progress);\n          container.appendChild(progressContainer);\n        } // Media current time display\n\n\n        if (control === 'current-time') {\n          container.appendChild(createTime.call(this, 'currentTime', defaultAttributes));\n        } // Media duration display\n\n\n        if (control === 'duration') {\n          container.appendChild(createTime.call(this, 'duration', defaultAttributes));\n        } // Volume controls\n\n\n        if (control === 'mute' || control === 'volume') {\n          let {\n            volume\n          } = this.elements; // Create the volume container if needed\n\n          if (!is.element(volume) || !container.contains(volume)) {\n            volume = createElement('div', extend({}, defaultAttributes, {\n              class: `${defaultAttributes.class} plyr__volume`.trim()\n            }));\n            this.elements.volume = volume;\n            container.appendChild(volume);\n          } // Toggle mute button\n\n\n          if (control === 'mute') {\n            volume.appendChild(createButton.call(this, 'mute'));\n          } // Volume range control\n          // Ignored on iOS as it's handled globally\n          // https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html\n\n\n          if (control === 'volume' && !browser.isIos) {\n            // Set the attributes\n            const attributes = {\n              max: 1,\n              step: 0.05,\n              value: this.config.volume\n            }; // Create the volume range slider\n\n            volume.appendChild(createRange.call(this, 'volume', extend(attributes, {\n              id: `plyr-volume-${data.id}`\n            })));\n          }\n        } // Toggle captions button\n\n\n        if (control === 'captions') {\n          container.appendChild(createButton.call(this, 'captions', defaultAttributes));\n        } // Settings button / menu\n\n\n        if (control === 'settings' && !is.empty(this.config.settings)) {\n          const wrapper = createElement('div', extend({}, defaultAttributes, {\n            class: `${defaultAttributes.class} plyr__menu`.trim(),\n            hidden: ''\n          }));\n          wrapper.appendChild(createButton.call(this, 'settings', {\n            'aria-haspopup': true,\n            'aria-controls': `plyr-settings-${data.id}`,\n            'aria-expanded': false\n          }));\n          const popup = createElement('div', {\n            class: 'plyr__menu__container',\n            id: `plyr-settings-${data.id}`,\n            hidden: ''\n          });\n          const inner = createElement('div');\n          const home = createElement('div', {\n            id: `plyr-settings-${data.id}-home`\n          }); // Create the menu\n\n          const menu = createElement('div', {\n            role: 'menu'\n          });\n          home.appendChild(menu);\n          inner.appendChild(home);\n          this.elements.settings.panels.home = home; // Build the menu items\n\n          this.config.settings.forEach(type => {\n            // TODO: bundle this with the createMenuItem helper and bindings\n            const menuItem = createElement('button', extend(getAttributesFromSelector(this.config.selectors.buttons.settings), {\n              type: 'button',\n              class: `${this.config.classNames.control} ${this.config.classNames.control}--forward`,\n              role: 'menuitem',\n              'aria-haspopup': true,\n              hidden: ''\n            })); // Bind menu shortcuts for keyboard users\n\n            bindMenuItemShortcuts.call(this, menuItem, type); // Show menu on click\n\n            on.call(this, menuItem, 'click', () => {\n              showMenuPanel.call(this, type, false);\n            });\n            const flex = createElement('span', null, i18n.get(type, this.config));\n            const value = createElement('span', {\n              class: this.config.classNames.menu.value\n            }); // Speed contains HTML entities\n\n            value.innerHTML = data[type];\n            flex.appendChild(value);\n            menuItem.appendChild(flex);\n            menu.appendChild(menuItem); // Build the panes\n\n            const pane = createElement('div', {\n              id: `plyr-settings-${data.id}-${type}`,\n              hidden: ''\n            }); // Back button\n\n            const backButton = createElement('button', {\n              type: 'button',\n              class: `${this.config.classNames.control} ${this.config.classNames.control}--back`\n            }); // Visible label\n\n            backButton.appendChild(createElement('span', {\n              'aria-hidden': true\n            }, i18n.get(type, this.config))); // Screen reader label\n\n            backButton.appendChild(createElement('span', {\n              class: this.config.classNames.hidden\n            }, i18n.get('menuBack', this.config))); // Go back via keyboard\n\n            on.call(this, pane, 'keydown', event => {\n              // We only care about <-\n              if (event.which !== 37) {\n                return;\n              } // Prevent seek\n\n\n              event.preventDefault();\n              event.stopPropagation(); // Show the respective menu\n\n              showMenuPanel.call(this, 'home', true);\n            }, false); // Go back via button click\n\n            on.call(this, backButton, 'click', () => {\n              showMenuPanel.call(this, 'home', false);\n            }); // Add to pane\n\n            pane.appendChild(backButton); // Menu\n\n            pane.appendChild(createElement('div', {\n              role: 'menu'\n            }));\n            inner.appendChild(pane);\n            this.elements.settings.buttons[type] = menuItem;\n            this.elements.settings.panels[type] = pane;\n          });\n          popup.appendChild(inner);\n          wrapper.appendChild(popup);\n          container.appendChild(wrapper);\n          this.elements.settings.popup = popup;\n          this.elements.settings.menu = wrapper;\n        } // Picture in picture button\n\n\n        if (control === 'pip' && support.pip) {\n          container.appendChild(createButton.call(this, 'pip', defaultAttributes));\n        } // Airplay button\n\n\n        if (control === 'airplay' && support.airplay) {\n          container.appendChild(createButton.call(this, 'airplay', defaultAttributes));\n        } // Download button\n\n\n        if (control === 'download') {\n          const attributes = extend({}, defaultAttributes, {\n            element: 'a',\n            href: this.download,\n            target: '_blank'\n          }); // Set download attribute for HTML5 only\n\n          if (this.isHTML5) {\n            attributes.download = '';\n          }\n\n          const {\n            download\n          } = this.config.urls;\n\n          if (!is.url(download) && this.isEmbed) {\n            extend(attributes, {\n              icon: `logo-${this.provider}`,\n              label: this.provider\n            });\n          }\n\n          container.appendChild(createButton.call(this, 'download', attributes));\n        } // Toggle fullscreen button\n\n\n        if (control === 'fullscreen') {\n          container.appendChild(createButton.call(this, 'fullscreen', defaultAttributes));\n        }\n      }); // Set available quality levels\n\n      if (this.isHTML5) {\n        setQualityMenu.call(this, html5.getQualityOptions.call(this));\n      }\n\n      setSpeedMenu.call(this);\n      return container;\n    },\n\n    // Insert controls\n    inject() {\n      // Sprite\n      if (this.config.loadSprite) {\n        const icon = controls.getIconUrl.call(this); // Only load external sprite using AJAX\n\n        if (icon.cors) {\n          loadSprite(icon.url, 'sprite-plyr');\n        }\n      } // Create a unique ID\n\n\n      this.id = Math.floor(Math.random() * 10000); // Null by default\n\n      let container = null;\n      this.elements.controls = null; // Set template properties\n\n      const props = {\n        id: this.id,\n        seektime: this.config.seekTime,\n        title: this.config.title\n      };\n      let update = true; // If function, run it and use output\n\n      if (is.function(this.config.controls)) {\n        this.config.controls = this.config.controls.call(this, props);\n      } // Convert falsy controls to empty array (primarily for empty strings)\n\n\n      if (!this.config.controls) {\n        this.config.controls = [];\n      }\n\n      if (is.element(this.config.controls) || is.string(this.config.controls)) {\n        // HTMLElement or Non-empty string passed as the option\n        container = this.config.controls;\n      } else {\n        // Create controls\n        container = controls.create.call(this, {\n          id: this.id,\n          seektime: this.config.seekTime,\n          speed: this.speed,\n          quality: this.quality,\n          captions: captions.getLabel.call(this) // TODO: Looping\n          // loop: 'None',\n\n        });\n        update = false;\n      } // Replace props with their value\n\n\n      const replace = input => {\n        let result = input;\n        Object.entries(props).forEach(([key, value]) => {\n          result = replaceAll(result, `{${key}}`, value);\n        });\n        return result;\n      }; // Update markup\n\n\n      if (update) {\n        if (is.string(this.config.controls)) {\n          container = replace(container);\n        }\n      } // Controls container\n\n\n      let target; // Inject to custom location\n\n      if (is.string(this.config.selectors.controls.container)) {\n        target = document.querySelector(this.config.selectors.controls.container);\n      } // Inject into the container by default\n\n\n      if (!is.element(target)) {\n        target = this.elements.container;\n      } // Inject controls HTML (needs to be before captions, hence \"afterbegin\")\n\n\n      const insertMethod = is.element(container) ? 'insertAdjacentElement' : 'insertAdjacentHTML';\n      target[insertMethod]('afterbegin', container); // Find the elements if need be\n\n      if (!is.element(this.elements.controls)) {\n        controls.findElements.call(this);\n      } // Add pressed property to buttons\n\n\n      if (!is.empty(this.elements.buttons)) {\n        const addProperty = button => {\n          const className = this.config.classNames.controlPressed;\n          Object.defineProperty(button, 'pressed', {\n            enumerable: true,\n\n            get() {\n              return hasClass(button, className);\n            },\n\n            set(pressed = false) {\n              toggleClass(button, className, pressed);\n            }\n\n          });\n        }; // Toggle classname when pressed property is set\n\n\n        Object.values(this.elements.buttons).filter(Boolean).forEach(button => {\n          if (is.array(button) || is.nodeList(button)) {\n            Array.from(button).filter(Boolean).forEach(addProperty);\n          } else {\n            addProperty(button);\n          }\n        });\n      } // Edge sometimes doesn't finish the paint so force a repaint\n\n\n      if (browser.isEdge) {\n        repaint(target);\n      } // Setup tooltips\n\n\n      if (this.config.tooltips.controls) {\n        const {\n          classNames,\n          selectors\n        } = this.config;\n        const selector = `${selectors.controls.wrapper} ${selectors.labels} .${classNames.hidden}`;\n        const labels = getElements.call(this, selector);\n        Array.from(labels).forEach(label => {\n          toggleClass(label, this.config.classNames.hidden, false);\n          toggleClass(label, this.config.classNames.tooltip, true);\n        });\n      }\n    }\n\n  };\n\n  // ==========================================================================\n  /**\n   * Parse a string to a URL object\n   * @param {String} input - the URL to be parsed\n   * @param {Boolean} safe - failsafe parsing\n   */\n\n  function parseUrl(input, safe = true) {\n    let url = input;\n\n    if (safe) {\n      const parser = document.createElement('a');\n      parser.href = url;\n      url = parser.href;\n    }\n\n    try {\n      return new URL(url);\n    } catch (_) {\n      return null;\n    }\n  } // Convert object to URLSearchParams\n\n  function buildUrlParams(input) {\n    const params = new URLSearchParams();\n\n    if (is.object(input)) {\n      Object.entries(input).forEach(([key, value]) => {\n        params.set(key, value);\n      });\n    }\n\n    return params;\n  }\n\n  // ==========================================================================\n  const captions = {\n    // Setup captions\n    setup() {\n      // Requires UI support\n      if (!this.supported.ui) {\n        return;\n      } // Only Vimeo and HTML5 video supported at this point\n\n\n      if (!this.isVideo || this.isYouTube || this.isHTML5 && !support.textTracks) {\n        // Clear menu and hide\n        if (is.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) {\n          controls.setCaptionsMenu.call(this);\n        }\n\n        return;\n      } // Inject the container\n\n\n      if (!is.element(this.elements.captions)) {\n        this.elements.captions = createElement('div', getAttributesFromSelector(this.config.selectors.captions));\n        insertAfter(this.elements.captions, this.elements.wrapper);\n      } // Fix IE captions if CORS is used\n      // Fetch captions and inject as blobs instead (data URIs not supported!)\n\n\n      if (browser.isIE && window.URL) {\n        const elements = this.media.querySelectorAll('track');\n        Array.from(elements).forEach(track => {\n          const src = track.getAttribute('src');\n          const url = parseUrl(src);\n\n          if (url !== null && url.hostname !== window.location.href.hostname && ['http:', 'https:'].includes(url.protocol)) {\n            fetch(src, 'blob').then(blob => {\n              track.setAttribute('src', window.URL.createObjectURL(blob));\n            }).catch(() => {\n              removeElement(track);\n            });\n          }\n        });\n      } // Get and set initial data\n      // The \"preferred\" options are not realized unless / until the wanted language has a match\n      // * languages: Array of user's browser languages.\n      // * language:  The language preferred by user settings or config\n      // * active:    The state preferred by user settings or config\n      // * toggled:   The real captions state\n\n\n      const browserLanguages = navigator.languages || [navigator.language || navigator.userLanguage || 'en'];\n      const languages = dedupe(browserLanguages.map(language => language.split('-')[0]));\n      let language = (this.storage.get('language') || this.config.captions.language || 'auto').toLowerCase(); // Use first browser language when language is 'auto'\n\n      if (language === 'auto') {\n        [language] = languages;\n      }\n\n      let active = this.storage.get('captions');\n\n      if (!is.boolean(active)) {\n        ({\n          active\n        } = this.config.captions);\n      }\n\n      Object.assign(this.captions, {\n        toggled: false,\n        active,\n        language,\n        languages\n      }); // Watch changes to textTracks and update captions menu\n\n      if (this.isHTML5) {\n        const trackEvents = this.config.captions.update ? 'addtrack removetrack' : 'removetrack';\n        on.call(this, this.media.textTracks, trackEvents, captions.update.bind(this));\n      } // Update available languages in list next tick (the event must not be triggered before the listeners)\n\n\n      setTimeout(captions.update.bind(this), 0);\n    },\n\n    // Update available language options in settings based on tracks\n    update() {\n      const tracks = captions.getTracks.call(this, true); // Get the wanted language\n\n      const {\n        active,\n        language,\n        meta,\n        currentTrackNode\n      } = this.captions;\n      const languageExists = Boolean(tracks.find(track => track.language === language)); // Handle tracks (add event listener and \"pseudo\"-default)\n\n      if (this.isHTML5 && this.isVideo) {\n        tracks.filter(track => !meta.get(track)).forEach(track => {\n          this.debug.log('Track added', track); // Attempt to store if the original dom element was \"default\"\n\n          meta.set(track, {\n            default: track.mode === 'showing'\n          }); // Turn off native caption rendering to avoid double captions\n          // Note: mode='hidden' forces a track to download. To ensure every track\n          // isn't downloaded at once, only 'showing' tracks should be reassigned\n          // eslint-disable-next-line no-param-reassign\n\n          if (track.mode === 'showing') {\n            // eslint-disable-next-line no-param-reassign\n            track.mode = 'hidden';\n          } // Add event listener for cue changes\n\n\n          on.call(this, track, 'cuechange', () => captions.updateCues.call(this));\n        });\n      } // Update language first time it matches, or if the previous matching track was removed\n\n\n      if (languageExists && this.language !== language || !tracks.includes(currentTrackNode)) {\n        captions.setLanguage.call(this, language);\n        captions.toggle.call(this, active && languageExists);\n      } // Enable or disable captions based on track length\n\n\n      if (this.elements) {\n        toggleClass(this.elements.container, this.config.classNames.captions.enabled, !is.empty(tracks));\n      } // Update available languages in list\n\n\n      if (is.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) {\n        controls.setCaptionsMenu.call(this);\n      }\n    },\n\n    // Toggle captions display\n    // Used internally for the toggleCaptions method, with the passive option forced to false\n    toggle(input, passive = true) {\n      // If there's no full support\n      if (!this.supported.ui) {\n        return;\n      }\n\n      const {\n        toggled\n      } = this.captions; // Current state\n\n      const activeClass = this.config.classNames.captions.active; // Get the next state\n      // If the method is called without parameter, toggle based on current value\n\n      const active = is.nullOrUndefined(input) ? !toggled : input; // Update state and trigger event\n\n      if (active !== toggled) {\n        // When passive, don't override user preferences\n        if (!passive) {\n          this.captions.active = active;\n          this.storage.set({\n            captions: active\n          });\n        } // Force language if the call isn't passive and there is no matching language to toggle to\n\n\n        if (!this.language && active && !passive) {\n          const tracks = captions.getTracks.call(this);\n          const track = captions.findTrack.call(this, [this.captions.language, ...this.captions.languages], true); // Override user preferences to avoid switching languages if a matching track is added\n\n          this.captions.language = track.language; // Set caption, but don't store in localStorage as user preference\n\n          captions.set.call(this, tracks.indexOf(track));\n          return;\n        } // Toggle button if it's enabled\n\n\n        if (this.elements.buttons.captions) {\n          this.elements.buttons.captions.pressed = active;\n        } // Add class hook\n\n\n        toggleClass(this.elements.container, activeClass, active);\n        this.captions.toggled = active; // Update settings menu\n\n        controls.updateSetting.call(this, 'captions'); // Trigger event (not used internally)\n\n        triggerEvent.call(this, this.media, active ? 'captionsenabled' : 'captionsdisabled');\n      } // Wait for the call stack to clear before setting mode='hidden'\n      // on the active track - forcing the browser to download it\n\n\n      setTimeout(() => {\n        if (active && this.captions.toggled) {\n          this.captions.currentTrackNode.mode = 'hidden';\n        }\n      });\n    },\n\n    // Set captions by track index\n    // Used internally for the currentTrack setter with the passive option forced to false\n    set(index, passive = true) {\n      const tracks = captions.getTracks.call(this); // Disable captions if setting to -1\n\n      if (index === -1) {\n        captions.toggle.call(this, false, passive);\n        return;\n      }\n\n      if (!is.number(index)) {\n        this.debug.warn('Invalid caption argument', index);\n        return;\n      }\n\n      if (!(index in tracks)) {\n        this.debug.warn('Track not found', index);\n        return;\n      }\n\n      if (this.captions.currentTrack !== index) {\n        this.captions.currentTrack = index;\n        const track = tracks[index];\n        const {\n          language\n        } = track || {}; // Store reference to node for invalidation on remove\n\n        this.captions.currentTrackNode = track; // Update settings menu\n\n        controls.updateSetting.call(this, 'captions'); // When passive, don't override user preferences\n\n        if (!passive) {\n          this.captions.language = language;\n          this.storage.set({\n            language\n          });\n        } // Handle Vimeo captions\n\n\n        if (this.isVimeo) {\n          this.embed.enableTextTrack(language);\n        } // Trigger event\n\n\n        triggerEvent.call(this, this.media, 'languagechange');\n      } // Show captions\n\n\n      captions.toggle.call(this, true, passive);\n\n      if (this.isHTML5 && this.isVideo) {\n        // If we change the active track while a cue is already displayed we need to update it\n        captions.updateCues.call(this);\n      }\n    },\n\n    // Set captions by language\n    // Used internally for the language setter with the passive option forced to false\n    setLanguage(input, passive = true) {\n      if (!is.string(input)) {\n        this.debug.warn('Invalid language argument', input);\n        return;\n      } // Normalize\n\n\n      const language = input.toLowerCase();\n      this.captions.language = language; // Set currentTrack\n\n      const tracks = captions.getTracks.call(this);\n      const track = captions.findTrack.call(this, [language]);\n      captions.set.call(this, tracks.indexOf(track), passive);\n    },\n\n    // Get current valid caption tracks\n    // If update is false it will also ignore tracks without metadata\n    // This is used to \"freeze\" the language options when captions.update is false\n    getTracks(update = false) {\n      // Handle media or textTracks missing or null\n      const tracks = Array.from((this.media || {}).textTracks || []); // For HTML5, use cache instead of current tracks when it exists (if captions.update is false)\n      // Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata)\n\n      return tracks.filter(track => !this.isHTML5 || update || this.captions.meta.has(track)).filter(track => ['captions', 'subtitles'].includes(track.kind));\n    },\n\n    // Match tracks based on languages and get the first\n    findTrack(languages, force = false) {\n      const tracks = captions.getTracks.call(this);\n\n      const sortIsDefault = track => Number((this.captions.meta.get(track) || {}).default);\n\n      const sorted = Array.from(tracks).sort((a, b) => sortIsDefault(b) - sortIsDefault(a));\n      let track;\n      languages.every(language => {\n        track = sorted.find(t => t.language === language);\n        return !track; // Break iteration if there is a match\n      }); // If no match is found but is required, get first\n\n      return track || (force ? sorted[0] : undefined);\n    },\n\n    // Get the current track\n    getCurrentTrack() {\n      return captions.getTracks.call(this)[this.currentTrack];\n    },\n\n    // Get UI label for track\n    getLabel(track) {\n      let currentTrack = track;\n\n      if (!is.track(currentTrack) && support.textTracks && this.captions.toggled) {\n        currentTrack = captions.getCurrentTrack.call(this);\n      }\n\n      if (is.track(currentTrack)) {\n        if (!is.empty(currentTrack.label)) {\n          return currentTrack.label;\n        }\n\n        if (!is.empty(currentTrack.language)) {\n          return track.language.toUpperCase();\n        }\n\n        return i18n.get('enabled', this.config);\n      }\n\n      return i18n.get('disabled', this.config);\n    },\n\n    // Update captions using current track's active cues\n    // Also optional array argument in case there isn't any track (ex: vimeo)\n    updateCues(input) {\n      // Requires UI\n      if (!this.supported.ui) {\n        return;\n      }\n\n      if (!is.element(this.elements.captions)) {\n        this.debug.warn('No captions element to render to');\n        return;\n      } // Only accept array or empty input\n\n\n      if (!is.nullOrUndefined(input) && !Array.isArray(input)) {\n        this.debug.warn('updateCues: Invalid input', input);\n        return;\n      }\n\n      let cues = input; // Get cues from track\n\n      if (!cues) {\n        const track = captions.getCurrentTrack.call(this);\n        cues = Array.from((track || {}).activeCues || []).map(cue => cue.getCueAsHTML()).map(getHTML);\n      } // Set new caption text\n\n\n      const content = cues.map(cueText => cueText.trim()).join('\\n');\n      const changed = content !== this.elements.captions.innerHTML;\n\n      if (changed) {\n        // Empty the container and create a new child element\n        emptyElement(this.elements.captions);\n        const caption = createElement('span', getAttributesFromSelector(this.config.selectors.caption));\n        caption.innerHTML = content;\n        this.elements.captions.appendChild(caption); // Trigger event\n\n        triggerEvent.call(this, this.media, 'cuechange');\n      }\n    }\n\n  };\n\n  // ==========================================================================\n  // Plyr default config\n  // ==========================================================================\n  const defaults = {\n    // Disable\n    enabled: true,\n    // Custom media title\n    title: '',\n    // Logging to console\n    debug: false,\n    // Auto play (if supported)\n    autoplay: false,\n    // Only allow one media playing at once (vimeo only)\n    autopause: true,\n    // Allow inline playback on iOS (this effects YouTube/Vimeo - HTML5 requires the attribute present)\n    // TODO: Remove iosNative fullscreen option in favour of this (logic needs work)\n    playsinline: true,\n    // Default time to skip when rewind/fast forward\n    seekTime: 10,\n    // Default volume\n    volume: 1,\n    muted: false,\n    // Pass a custom duration\n    duration: null,\n    // Display the media duration on load in the current time position\n    // If you have opted to display both duration and currentTime, this is ignored\n    displayDuration: true,\n    // Invert the current time to be a countdown\n    invertTime: true,\n    // Clicking the currentTime inverts it's value to show time left rather than elapsed\n    toggleInvert: true,\n    // Force an aspect ratio\n    // The format must be `'w:h'` (e.g. `'16:9'`)\n    ratio: null,\n    // Click video container to play/pause\n    clickToPlay: true,\n    // Auto hide the controls\n    hideControls: true,\n    // Reset to start when playback ended\n    resetOnEnd: false,\n    // Disable the standard context menu\n    disableContextMenu: true,\n    // Sprite (for icons)\n    loadSprite: true,\n    iconPrefix: 'plyr',\n    iconUrl: 'https://cdn.plyr.io/3.6.12/plyr.svg',\n    // Blank video (used to prevent errors on source change)\n    blankVideo: 'https://cdn.plyr.io/static/blank.mp4',\n    // Quality default\n    quality: {\n      default: 576,\n      // The options to display in the UI, if available for the source media\n      options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240],\n      forced: false,\n      onChange: null\n    },\n    // Set loops\n    loop: {\n      active: false // start: null,\n      // end: null,\n\n    },\n    // Speed default and options to display\n    speed: {\n      selected: 1,\n      // The options to display in the UI, if available for the source media (e.g. Vimeo and YouTube only support 0.5x-4x)\n      options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 4]\n    },\n    // Keyboard shortcut settings\n    keyboard: {\n      focused: true,\n      global: false\n    },\n    // Display tooltips\n    tooltips: {\n      controls: false,\n      seek: true\n    },\n    // Captions settings\n    captions: {\n      active: false,\n      language: 'auto',\n      // Listen to new tracks added after Plyr is initialized.\n      // This is needed for streaming captions, but may result in unselectable options\n      update: false\n    },\n    // Fullscreen settings\n    fullscreen: {\n      enabled: true,\n      // Allow fullscreen?\n      fallback: true,\n      // Fallback using full viewport/window\n      iosNative: false // Use the native fullscreen in iOS (disables custom controls)\n      // Selector for the fullscreen container so contextual / non-player content can remain visible in fullscreen mode\n      // Non-ancestors of the player element will be ignored\n      // container: null, // defaults to the player element\n\n    },\n    // Local storage\n    storage: {\n      enabled: true,\n      key: 'plyr'\n    },\n    // Default controls\n    controls: ['play-large', // 'restart',\n    // 'rewind',\n    'play', // 'fast-forward',\n    'progress', 'current-time', // 'duration',\n    'mute', 'volume', 'captions', 'settings', 'pip', 'airplay', // 'download',\n    'fullscreen'],\n    settings: ['captions', 'quality', 'speed'],\n    // Localisation\n    i18n: {\n      restart: 'Restart',\n      rewind: 'Rewind {seektime}s',\n      play: 'Play',\n      pause: 'Pause',\n      fastForward: 'Forward {seektime}s',\n      seek: 'Seek',\n      seekLabel: '{currentTime} of {duration}',\n      played: 'Played',\n      buffered: 'Buffered',\n      currentTime: 'Current time',\n      duration: 'Duration',\n      volume: 'Volume',\n      mute: 'Mute',\n      unmute: 'Unmute',\n      enableCaptions: 'Enable captions',\n      disableCaptions: 'Disable captions',\n      download: 'Download',\n      enterFullscreen: 'Enter fullscreen',\n      exitFullscreen: 'Exit fullscreen',\n      frameTitle: 'Player for {title}',\n      captions: 'Captions',\n      settings: 'Settings',\n      pip: 'PIP',\n      menuBack: 'Go back to previous menu',\n      speed: 'Speed',\n      normal: 'Normal',\n      quality: 'Quality',\n      loop: 'Loop',\n      start: 'Start',\n      end: 'End',\n      all: 'All',\n      reset: 'Reset',\n      disabled: 'Disabled',\n      enabled: 'Enabled',\n      advertisement: 'Ad',\n      qualityBadge: {\n        2160: '4K',\n        1440: 'HD',\n        1080: 'HD',\n        720: 'HD',\n        576: 'SD',\n        480: 'SD'\n      }\n    },\n    // URLs\n    urls: {\n      download: null,\n      vimeo: {\n        sdk: 'https://player.vimeo.com/api/player.js',\n        iframe: 'https://player.vimeo.com/video/{0}?{1}',\n        api: 'https://vimeo.com/api/oembed.json?url={0}'\n      },\n      youtube: {\n        sdk: 'https://www.youtube.com/iframe_api',\n        api: 'https://noembed.com/embed?url=https://www.youtube.com/watch?v={0}'\n      },\n      googleIMA: {\n        sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js'\n      }\n    },\n    // Custom control listeners\n    listeners: {\n      seek: null,\n      play: null,\n      pause: null,\n      restart: null,\n      rewind: null,\n      fastForward: null,\n      mute: null,\n      volume: null,\n      captions: null,\n      download: null,\n      fullscreen: null,\n      pip: null,\n      airplay: null,\n      speed: null,\n      quality: null,\n      loop: null,\n      language: null\n    },\n    // Events to watch and bubble\n    events: [// Events to watch on HTML5 media elements and bubble\n    // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events\n    'ended', 'progress', 'stalled', 'playing', 'waiting', 'canplay', 'canplaythrough', 'loadstart', 'loadeddata', 'loadedmetadata', 'timeupdate', 'volumechange', 'play', 'pause', 'error', 'seeking', 'seeked', 'emptied', 'ratechange', 'cuechange', // Custom events\n    'download', 'enterfullscreen', 'exitfullscreen', 'captionsenabled', 'captionsdisabled', 'languagechange', 'controlshidden', 'controlsshown', 'ready', // YouTube\n    'statechange', // Quality\n    'qualitychange', // Ads\n    'adsloaded', 'adscontentpause', 'adscontentresume', 'adstarted', 'adsmidpoint', 'adscomplete', 'adsallcomplete', 'adsimpression', 'adsclick'],\n    // Selectors\n    // Change these to match your template if using custom HTML\n    selectors: {\n      editable: 'input, textarea, select, [contenteditable]',\n      container: '.plyr',\n      controls: {\n        container: null,\n        wrapper: '.plyr__controls'\n      },\n      labels: '[data-plyr]',\n      buttons: {\n        play: '[data-plyr=\"play\"]',\n        pause: '[data-plyr=\"pause\"]',\n        restart: '[data-plyr=\"restart\"]',\n        rewind: '[data-plyr=\"rewind\"]',\n        fastForward: '[data-plyr=\"fast-forward\"]',\n        mute: '[data-plyr=\"mute\"]',\n        captions: '[data-plyr=\"captions\"]',\n        download: '[data-plyr=\"download\"]',\n        fullscreen: '[data-plyr=\"fullscreen\"]',\n        pip: '[data-plyr=\"pip\"]',\n        airplay: '[data-plyr=\"airplay\"]',\n        settings: '[data-plyr=\"settings\"]',\n        loop: '[data-plyr=\"loop\"]'\n      },\n      inputs: {\n        seek: '[data-plyr=\"seek\"]',\n        volume: '[data-plyr=\"volume\"]',\n        speed: '[data-plyr=\"speed\"]',\n        language: '[data-plyr=\"language\"]',\n        quality: '[data-plyr=\"quality\"]'\n      },\n      display: {\n        currentTime: '.plyr__time--current',\n        duration: '.plyr__time--duration',\n        buffer: '.plyr__progress__buffer',\n        loop: '.plyr__progress__loop',\n        // Used later\n        volume: '.plyr__volume--display'\n      },\n      progress: '.plyr__progress',\n      captions: '.plyr__captions',\n      caption: '.plyr__caption'\n    },\n    // Class hooks added to the player in different states\n    classNames: {\n      type: 'plyr--{0}',\n      provider: 'plyr--{0}',\n      video: 'plyr__video-wrapper',\n      embed: 'plyr__video-embed',\n      videoFixedRatio: 'plyr__video-wrapper--fixed-ratio',\n      embedContainer: 'plyr__video-embed__container',\n      poster: 'plyr__poster',\n      posterEnabled: 'plyr__poster-enabled',\n      ads: 'plyr__ads',\n      control: 'plyr__control',\n      controlPressed: 'plyr__control--pressed',\n      playing: 'plyr--playing',\n      paused: 'plyr--paused',\n      stopped: 'plyr--stopped',\n      loading: 'plyr--loading',\n      hover: 'plyr--hover',\n      tooltip: 'plyr__tooltip',\n      cues: 'plyr__cues',\n      hidden: 'plyr__sr-only',\n      hideControls: 'plyr--hide-controls',\n      isIos: 'plyr--is-ios',\n      isTouch: 'plyr--is-touch',\n      uiSupported: 'plyr--full-ui',\n      noTransition: 'plyr--no-transition',\n      display: {\n        time: 'plyr__time'\n      },\n      menu: {\n        value: 'plyr__menu__value',\n        badge: 'plyr__badge',\n        open: 'plyr--menu-open'\n      },\n      captions: {\n        enabled: 'plyr--captions-enabled',\n        active: 'plyr--captions-active'\n      },\n      fullscreen: {\n        enabled: 'plyr--fullscreen-enabled',\n        fallback: 'plyr--fullscreen-fallback'\n      },\n      pip: {\n        supported: 'plyr--pip-supported',\n        active: 'plyr--pip-active'\n      },\n      airplay: {\n        supported: 'plyr--airplay-supported',\n        active: 'plyr--airplay-active'\n      },\n      tabFocus: 'plyr__tab-focus',\n      previewThumbnails: {\n        // Tooltip thumbs\n        thumbContainer: 'plyr__preview-thumb',\n        thumbContainerShown: 'plyr__preview-thumb--is-shown',\n        imageContainer: 'plyr__preview-thumb__image-container',\n        timeContainer: 'plyr__preview-thumb__time-container',\n        // Scrubbing\n        scrubbingContainer: 'plyr__preview-scrubbing',\n        scrubbingContainerShown: 'plyr__preview-scrubbing--is-shown'\n      }\n    },\n    // Embed attributes\n    attributes: {\n      embed: {\n        provider: 'data-plyr-provider',\n        id: 'data-plyr-embed-id',\n        hash: 'data-plyr-embed-hash'\n      }\n    },\n    // Advertisements plugin\n    // Register for an account here: http://vi.ai/publisher-video-monetization/?aid=plyrio\n    ads: {\n      enabled: false,\n      publisherId: '',\n      tagUrl: ''\n    },\n    // Preview Thumbnails plugin\n    previewThumbnails: {\n      enabled: false,\n      src: ''\n    },\n    // Vimeo plugin\n    vimeo: {\n      byline: false,\n      portrait: false,\n      title: false,\n      speed: true,\n      transparent: false,\n      // Custom settings from Plyr\n      customControls: true,\n      referrerPolicy: null,\n      // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy\n      // Whether the owner of the video has a Pro or Business account\n      // (which allows us to properly hide controls without CSS hacks, etc)\n      premium: false\n    },\n    // YouTube plugin\n    youtube: {\n      rel: 0,\n      // No related vids\n      showinfo: 0,\n      // Hide info\n      iv_load_policy: 3,\n      // Hide annotations\n      modestbranding: 1,\n      // Hide logos as much as possible (they still show one in the corner when paused)\n      // Custom settings from Plyr\n      customControls: true,\n      noCookie: false // Whether to use an alternative version of YouTube without cookies\n\n    }\n  };\n\n  // ==========================================================================\n  // Plyr states\n  // ==========================================================================\n  const pip = {\n    active: 'picture-in-picture',\n    inactive: 'inline'\n  };\n\n  // ==========================================================================\n  // Plyr supported types and providers\n  // ==========================================================================\n  const providers = {\n    html5: 'html5',\n    youtube: 'youtube',\n    vimeo: 'vimeo'\n  };\n  const types = {\n    audio: 'audio',\n    video: 'video'\n  };\n  /**\n   * Get provider by URL\n   * @param {String} url\n   */\n\n  function getProviderByUrl(url) {\n    // YouTube\n    if (/^(https?:\\/\\/)?(www\\.)?(youtube\\.com|youtube-nocookie\\.com|youtu\\.?be)\\/.+$/.test(url)) {\n      return providers.youtube;\n    } // Vimeo\n\n\n    if (/^https?:\\/\\/player.vimeo.com\\/video\\/\\d{0,9}(?=\\b|\\/)/.test(url)) {\n      return providers.vimeo;\n    }\n\n    return null;\n  }\n\n  // ==========================================================================\n  // Console wrapper\n  // ==========================================================================\n  const noop = () => {};\n\n  class Console {\n    constructor(enabled = false) {\n      this.enabled = window.console && enabled;\n\n      if (this.enabled) {\n        this.log('Debugging enabled');\n      }\n    }\n\n    get log() {\n      // eslint-disable-next-line no-console\n      return this.enabled ? Function.prototype.bind.call(console.log, console) : noop;\n    }\n\n    get warn() {\n      // eslint-disable-next-line no-console\n      return this.enabled ? Function.prototype.bind.call(console.warn, console) : noop;\n    }\n\n    get error() {\n      // eslint-disable-next-line no-console\n      return this.enabled ? Function.prototype.bind.call(console.error, console) : noop;\n    }\n\n  }\n\n  class Fullscreen {\n    constructor(player) {\n      _defineProperty$1(this, \"onChange\", () => {\n        if (!this.enabled) {\n          return;\n        } // Update toggle button\n\n\n        const button = this.player.elements.buttons.fullscreen;\n\n        if (is.element(button)) {\n          button.pressed = this.active;\n        } // Always trigger events on the plyr / media element (not a fullscreen container) and let them bubble up\n\n\n        const target = this.target === this.player.media ? this.target : this.player.elements.container; // Trigger an event\n\n        triggerEvent.call(this.player, target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);\n      });\n\n      _defineProperty$1(this, \"toggleFallback\", (toggle = false) => {\n        // Store or restore scroll position\n        if (toggle) {\n          this.scrollPosition = {\n            x: window.scrollX || 0,\n            y: window.scrollY || 0\n          };\n        } else {\n          window.scrollTo(this.scrollPosition.x, this.scrollPosition.y);\n        } // Toggle scroll\n\n\n        document.body.style.overflow = toggle ? 'hidden' : ''; // Toggle class hook\n\n        toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle); // Force full viewport on iPhone X+\n\n        if (browser.isIos) {\n          let viewport = document.head.querySelector('meta[name=\"viewport\"]');\n          const property = 'viewport-fit=cover'; // Inject the viewport meta if required\n\n          if (!viewport) {\n            viewport = document.createElement('meta');\n            viewport.setAttribute('name', 'viewport');\n          } // Check if the property already exists\n\n\n          const hasProperty = is.string(viewport.content) && viewport.content.includes(property);\n\n          if (toggle) {\n            this.cleanupViewport = !hasProperty;\n\n            if (!hasProperty) {\n              viewport.content += `,${property}`;\n            }\n          } else if (this.cleanupViewport) {\n            viewport.content = viewport.content.split(',').filter(part => part.trim() !== property).join(',');\n          }\n        } // Toggle button and fire events\n\n\n        this.onChange();\n      });\n\n      _defineProperty$1(this, \"trapFocus\", event => {\n        // Bail if iOS, not active, not the tab key\n        if (browser.isIos || !this.active || event.key !== 'Tab' || event.keyCode !== 9) {\n          return;\n        } // Get the current focused element\n\n\n        const focused = document.activeElement;\n        const focusable = getElements.call(this.player, 'a[href], button:not(:disabled), input:not(:disabled), [tabindex]');\n        const [first] = focusable;\n        const last = focusable[focusable.length - 1];\n\n        if (focused === last && !event.shiftKey) {\n          // Move focus to first element that can be tabbed if Shift isn't used\n          first.focus();\n          event.preventDefault();\n        } else if (focused === first && event.shiftKey) {\n          // Move focus to last element that can be tabbed if Shift is used\n          last.focus();\n          event.preventDefault();\n        }\n      });\n\n      _defineProperty$1(this, \"update\", () => {\n        if (this.enabled) {\n          let mode;\n\n          if (this.forceFallback) {\n            mode = 'Fallback (forced)';\n          } else if (Fullscreen.native) {\n            mode = 'Native';\n          } else {\n            mode = 'Fallback';\n          }\n\n          this.player.debug.log(`${mode} fullscreen enabled`);\n        } else {\n          this.player.debug.log('Fullscreen not supported and fallback disabled');\n        } // Add styling hook to show button\n\n\n        toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled);\n      });\n\n      _defineProperty$1(this, \"enter\", () => {\n        if (!this.enabled) {\n          return;\n        } // iOS native fullscreen doesn't need the request step\n\n\n        if (browser.isIos && this.player.config.fullscreen.iosNative) {\n          if (this.player.isVimeo) {\n            this.player.embed.requestFullscreen();\n          } else {\n            this.target.webkitEnterFullscreen();\n          }\n        } else if (!Fullscreen.native || this.forceFallback) {\n          this.toggleFallback(true);\n        } else if (!this.prefix) {\n          this.target.requestFullscreen({\n            navigationUI: 'hide'\n          });\n        } else if (!is.empty(this.prefix)) {\n          this.target[`${this.prefix}Request${this.property}`]();\n        }\n      });\n\n      _defineProperty$1(this, \"exit\", () => {\n        if (!this.enabled) {\n          return;\n        } // iOS native fullscreen\n\n\n        if (browser.isIos && this.player.config.fullscreen.iosNative) {\n          this.target.webkitExitFullscreen();\n          silencePromise(this.player.play());\n        } else if (!Fullscreen.native || this.forceFallback) {\n          this.toggleFallback(false);\n        } else if (!this.prefix) {\n          (document.cancelFullScreen || document.exitFullscreen).call(document);\n        } else if (!is.empty(this.prefix)) {\n          const action = this.prefix === 'moz' ? 'Cancel' : 'Exit';\n          document[`${this.prefix}${action}${this.property}`]();\n        }\n      });\n\n      _defineProperty$1(this, \"toggle\", () => {\n        if (!this.active) {\n          this.enter();\n        } else {\n          this.exit();\n        }\n      });\n\n      // Keep reference to parent\n      this.player = player; // Get prefix\n\n      this.prefix = Fullscreen.prefix;\n      this.property = Fullscreen.property; // Scroll position\n\n      this.scrollPosition = {\n        x: 0,\n        y: 0\n      }; // Force the use of 'full window/browser' rather than fullscreen\n\n      this.forceFallback = player.config.fullscreen.fallback === 'force'; // Get the fullscreen element\n      // Checks container is an ancestor, defaults to null\n\n      this.player.elements.fullscreen = player.config.fullscreen.container && closest$1(this.player.elements.container, player.config.fullscreen.container); // Register event listeners\n      // Handle event (incase user presses escape etc)\n\n      on.call(this.player, document, this.prefix === 'ms' ? 'MSFullscreenChange' : `${this.prefix}fullscreenchange`, () => {\n        // TODO: Filter for target??\n        this.onChange();\n      }); // Fullscreen toggle on double click\n\n      on.call(this.player, this.player.elements.container, 'dblclick', event => {\n        // Ignore double click in controls\n        if (is.element(this.player.elements.controls) && this.player.elements.controls.contains(event.target)) {\n          return;\n        }\n\n        this.player.listeners.proxy(event, this.toggle, 'fullscreen');\n      }); // Tap focus when in fullscreen\n\n      on.call(this, this.player.elements.container, 'keydown', event => this.trapFocus(event)); // Update the UI\n\n      this.update(); // this.toggle = this.toggle.bind(this);\n    } // Determine if native supported\n\n\n    static get native() {\n      return !!(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled);\n    } // If we're actually using native\n\n\n    get usingNative() {\n      return Fullscreen.native && !this.forceFallback;\n    } // Get the prefix for handlers\n\n\n    static get prefix() {\n      // No prefix\n      if (is.function(document.exitFullscreen)) {\n        return '';\n      } // Check for fullscreen support by vendor prefix\n\n\n      let value = '';\n      const prefixes = ['webkit', 'moz', 'ms'];\n      prefixes.some(pre => {\n        if (is.function(document[`${pre}ExitFullscreen`]) || is.function(document[`${pre}CancelFullScreen`])) {\n          value = pre;\n          return true;\n        }\n\n        return false;\n      });\n      return value;\n    }\n\n    static get property() {\n      return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen';\n    } // Determine if fullscreen is enabled\n\n\n    get enabled() {\n      return (Fullscreen.native || this.player.config.fullscreen.fallback) && this.player.config.fullscreen.enabled && this.player.supported.ui && this.player.isVideo;\n    } // Get active state\n\n\n    get active() {\n      if (!this.enabled) {\n        return false;\n      } // Fallback using classname\n\n\n      if (!Fullscreen.native || this.forceFallback) {\n        return hasClass(this.target, this.player.config.classNames.fullscreen.fallback);\n      }\n\n      const element = !this.prefix ? this.target.getRootNode().fullscreenElement : this.target.getRootNode()[`${this.prefix}${this.property}Element`];\n      return element && element.shadowRoot ? element === this.target.getRootNode().host : element === this.target;\n    } // Get target element\n\n\n    get target() {\n      return browser.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.fullscreen || this.player.elements.container;\n    }\n\n  }\n\n  // ==========================================================================\n  // Load image avoiding xhr/fetch CORS issues\n  // Server status can't be obtained this way unfortunately, so this uses \"naturalWidth\" to determine if the image has loaded\n  // By default it checks if it is at least 1px, but you can add a second argument to change this\n  // ==========================================================================\n  function loadImage(src, minWidth = 1) {\n    return new Promise((resolve, reject) => {\n      const image = new Image();\n\n      const handler = () => {\n        delete image.onload;\n        delete image.onerror;\n        (image.naturalWidth >= minWidth ? resolve : reject)(image);\n      };\n\n      Object.assign(image, {\n        onload: handler,\n        onerror: handler,\n        src\n      });\n    });\n  }\n\n  // ==========================================================================\n  const ui = {\n    addStyleHook() {\n      toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true);\n      toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui);\n    },\n\n    // Toggle native HTML5 media controls\n    toggleNativeControls(toggle = false) {\n      if (toggle && this.isHTML5) {\n        this.media.setAttribute('controls', '');\n      } else {\n        this.media.removeAttribute('controls');\n      }\n    },\n\n    // Setup the UI\n    build() {\n      // Re-attach media element listeners\n      // TODO: Use event bubbling?\n      this.listeners.media(); // Don't setup interface if no support\n\n      if (!this.supported.ui) {\n        this.debug.warn(`Basic support only for ${this.provider} ${this.type}`); // Restore native controls\n\n        ui.toggleNativeControls.call(this, true); // Bail\n\n        return;\n      } // Inject custom controls if not present\n\n\n      if (!is.element(this.elements.controls)) {\n        // Inject custom controls\n        controls.inject.call(this); // Re-attach control listeners\n\n        this.listeners.controls();\n      } // Remove native controls\n\n\n      ui.toggleNativeControls.call(this); // Setup captions for HTML5\n\n      if (this.isHTML5) {\n        captions.setup.call(this);\n      } // Reset volume\n\n\n      this.volume = null; // Reset mute state\n\n      this.muted = null; // Reset loop state\n\n      this.loop = null; // Reset quality setting\n\n      this.quality = null; // Reset speed\n\n      this.speed = null; // Reset volume display\n\n      controls.updateVolume.call(this); // Reset time display\n\n      controls.timeUpdate.call(this); // Reset duration display\n\n      controls.durationUpdate.call(this); // Update the UI\n\n      ui.checkPlaying.call(this); // Check for picture-in-picture support\n\n      toggleClass(this.elements.container, this.config.classNames.pip.supported, support.pip && this.isHTML5 && this.isVideo); // Check for airplay support\n\n      toggleClass(this.elements.container, this.config.classNames.airplay.supported, support.airplay && this.isHTML5); // Add iOS class\n\n      toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos); // Add touch class\n\n      toggleClass(this.elements.container, this.config.classNames.isTouch, this.touch); // Ready for API calls\n\n      this.ready = true; // Ready event at end of execution stack\n\n      setTimeout(() => {\n        triggerEvent.call(this, this.media, 'ready');\n      }, 0); // Set the title\n\n      ui.setTitle.call(this); // Assure the poster image is set, if the property was added before the element was created\n\n      if (this.poster) {\n        ui.setPoster.call(this, this.poster, false).catch(() => {});\n      } // Manually set the duration if user has overridden it.\n      // The event listeners for it doesn't get called if preload is disabled (#701)\n\n\n      if (this.config.duration) {\n        controls.durationUpdate.call(this);\n      }\n    },\n\n    // Setup aria attribute for play and iframe title\n    setTitle() {\n      // Find the current text\n      let label = i18n.get('play', this.config); // If there's a media title set, use that for the label\n\n      if (is.string(this.config.title) && !is.empty(this.config.title)) {\n        label += `, ${this.config.title}`;\n      } // If there's a play button, set label\n\n\n      Array.from(this.elements.buttons.play || []).forEach(button => {\n        button.setAttribute('aria-label', label);\n      }); // Set iframe title\n      // https://github.com/sampotts/plyr/issues/124\n\n      if (this.isEmbed) {\n        const iframe = getElement.call(this, 'iframe');\n\n        if (!is.element(iframe)) {\n          return;\n        } // Default to media type\n\n\n        const title = !is.empty(this.config.title) ? this.config.title : 'video';\n        const format = i18n.get('frameTitle', this.config);\n        iframe.setAttribute('title', format.replace('{title}', title));\n      }\n    },\n\n    // Toggle poster\n    togglePoster(enable) {\n      toggleClass(this.elements.container, this.config.classNames.posterEnabled, enable);\n    },\n\n    // Set the poster image (async)\n    // Used internally for the poster setter, with the passive option forced to false\n    setPoster(poster, passive = true) {\n      // Don't override if call is passive\n      if (passive && this.poster) {\n        return Promise.reject(new Error('Poster already set'));\n      } // Set property synchronously to respect the call order\n\n\n      this.media.setAttribute('data-poster', poster); // Show the poster\n\n      this.elements.poster.removeAttribute('hidden'); // Wait until ui is ready\n\n      return ready.call(this) // Load image\n      .then(() => loadImage(poster)).catch(error => {\n        // Hide poster on error unless it's been set by another call\n        if (poster === this.poster) {\n          ui.togglePoster.call(this, false);\n        } // Rethrow\n\n\n        throw error;\n      }).then(() => {\n        // Prevent race conditions\n        if (poster !== this.poster) {\n          throw new Error('setPoster cancelled by later call to setPoster');\n        }\n      }).then(() => {\n        Object.assign(this.elements.poster.style, {\n          backgroundImage: `url('${poster}')`,\n          // Reset backgroundSize as well (since it can be set to \"cover\" for padded thumbnails for youtube)\n          backgroundSize: ''\n        });\n        ui.togglePoster.call(this, true);\n        return poster;\n      });\n    },\n\n    // Check playing state\n    checkPlaying(event) {\n      // Class hooks\n      toggleClass(this.elements.container, this.config.classNames.playing, this.playing);\n      toggleClass(this.elements.container, this.config.classNames.paused, this.paused);\n      toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped); // Set state\n\n      Array.from(this.elements.buttons.play || []).forEach(target => {\n        Object.assign(target, {\n          pressed: this.playing\n        });\n        target.setAttribute('aria-label', i18n.get(this.playing ? 'pause' : 'play', this.config));\n      }); // Only update controls on non timeupdate events\n\n      if (is.event(event) && event.type === 'timeupdate') {\n        return;\n      } // Toggle controls\n\n\n      ui.toggleControls.call(this);\n    },\n\n    // Check if media is loading\n    checkLoading(event) {\n      this.loading = ['stalled', 'waiting'].includes(event.type); // Clear timer\n\n      clearTimeout(this.timers.loading); // Timer to prevent flicker when seeking\n\n      this.timers.loading = setTimeout(() => {\n        // Update progress bar loading class state\n        toggleClass(this.elements.container, this.config.classNames.loading, this.loading); // Update controls visibility\n\n        ui.toggleControls.call(this);\n      }, this.loading ? 250 : 0);\n    },\n\n    // Toggle controls based on state and `force` argument\n    toggleControls(force) {\n      const {\n        controls: controlsElement\n      } = this.elements;\n\n      if (controlsElement && this.config.hideControls) {\n        // Don't hide controls if a touch-device user recently seeked. (Must be limited to touch devices, or it occasionally prevents desktop controls from hiding.)\n        const recentTouchSeek = this.touch && this.lastSeekTime + 2000 > Date.now(); // Show controls if force, loading, paused, button interaction, or recent seek, otherwise hide\n\n        this.toggleControls(Boolean(force || this.loading || this.paused || controlsElement.pressed || controlsElement.hover || recentTouchSeek));\n      }\n    },\n\n    // Migrate any custom properties from the media to the parent\n    migrateStyles() {\n      // Loop through values (as they are the keys when the object is spread \uD83E\uDD14)\n      Object.values({ ...this.media.style\n      }) // We're only fussed about Plyr specific properties\n      .filter(key => !is.empty(key) && is.string(key) && key.startsWith('--plyr')).forEach(key => {\n        // Set on the container\n        this.elements.container.style.setProperty(key, this.media.style.getPropertyValue(key)); // Clean up from media element\n\n        this.media.style.removeProperty(key);\n      }); // Remove attribute if empty\n\n      if (is.empty(this.media.style)) {\n        this.media.removeAttribute('style');\n      }\n    }\n\n  };\n\n  class Listeners {\n    constructor(_player) {\n      _defineProperty$1(this, \"firstTouch\", () => {\n        const {\n          player\n        } = this;\n        const {\n          elements\n        } = player;\n        player.touch = true; // Add touch class\n\n        toggleClass(elements.container, player.config.classNames.isTouch, true);\n      });\n\n      _defineProperty$1(this, \"setTabFocus\", event => {\n        const {\n          player\n        } = this;\n        const {\n          elements\n        } = player;\n        clearTimeout(this.focusTimer); // Ignore any key other than tab\n\n        if (event.type === 'keydown' && event.which !== 9) {\n          return;\n        } // Store reference to event timeStamp\n\n\n        if (event.type === 'keydown') {\n          this.lastKeyDown = event.timeStamp;\n        } // Remove current classes\n\n\n        const removeCurrent = () => {\n          const className = player.config.classNames.tabFocus;\n          const current = getElements.call(player, `.${className}`);\n          toggleClass(current, className, false);\n        }; // Determine if a key was pressed to trigger this event\n\n\n        const wasKeyDown = event.timeStamp - this.lastKeyDown <= 20; // Ignore focus events if a key was pressed prior\n\n        if (event.type === 'focus' && !wasKeyDown) {\n          return;\n        } // Remove all current\n\n\n        removeCurrent(); // Delay the adding of classname until the focus has changed\n        // This event fires before the focusin event\n\n        if (event.type !== 'focusout') {\n          this.focusTimer = setTimeout(() => {\n            const focused = document.activeElement; // Ignore if current focus element isn't inside the player\n\n            if (!elements.container.contains(focused)) {\n              return;\n            }\n\n            toggleClass(document.activeElement, player.config.classNames.tabFocus, true);\n          }, 10);\n        }\n      });\n\n      _defineProperty$1(this, \"global\", (toggle = true) => {\n        const {\n          player\n        } = this; // Keyboard shortcuts\n\n        if (player.config.keyboard.global) {\n          toggleListener.call(player, window, 'keydown keyup', this.handleKey, toggle, false);\n        } // Click anywhere closes menu\n\n\n        toggleListener.call(player, document.body, 'click', this.toggleMenu, toggle); // Detect touch by events\n\n        once.call(player, document.body, 'touchstart', this.firstTouch); // Tab focus detection\n\n        toggleListener.call(player, document.body, 'keydown focus blur focusout', this.setTabFocus, toggle, false, true);\n      });\n\n      _defineProperty$1(this, \"container\", () => {\n        const {\n          player\n        } = this;\n        const {\n          config,\n          elements,\n          timers\n        } = player; // Keyboard shortcuts\n\n        if (!config.keyboard.global && config.keyboard.focused) {\n          on.call(player, elements.container, 'keydown keyup', this.handleKey, false);\n        } // Toggle controls on mouse events and entering fullscreen\n\n\n        on.call(player, elements.container, 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen', event => {\n          const {\n            controls: controlsElement\n          } = elements; // Remove button states for fullscreen\n\n          if (controlsElement && event.type === 'enterfullscreen') {\n            controlsElement.pressed = false;\n            controlsElement.hover = false;\n          } // Show, then hide after a timeout unless another control event occurs\n\n\n          const show = ['touchstart', 'touchmove', 'mousemove'].includes(event.type);\n          let delay = 0;\n\n          if (show) {\n            ui.toggleControls.call(player, true); // Use longer timeout for touch devices\n\n            delay = player.touch ? 3000 : 2000;\n          } // Clear timer\n\n\n          clearTimeout(timers.controls); // Set new timer to prevent flicker when seeking\n\n          timers.controls = setTimeout(() => ui.toggleControls.call(player, false), delay);\n        }); // Set a gutter for Vimeo\n\n        const setGutter = () => {\n          if (!player.isVimeo || player.config.vimeo.premium) {\n            return;\n          }\n\n          const target = elements.wrapper;\n          const {\n            active\n          } = player.fullscreen;\n          const [videoWidth, videoHeight] = getAspectRatio.call(player);\n          const useNativeAspectRatio = supportsCSS(`aspect-ratio: ${videoWidth} / ${videoHeight}`); // If not active, remove styles\n\n          if (!active) {\n            if (useNativeAspectRatio) {\n              target.style.width = null;\n              target.style.height = null;\n            } else {\n              target.style.maxWidth = null;\n              target.style.margin = null;\n            }\n\n            return;\n          } // Determine which dimension will overflow and constrain view\n\n\n          const [viewportWidth, viewportHeight] = getViewportSize();\n          const overflow = viewportWidth / viewportHeight > videoWidth / videoHeight;\n\n          if (useNativeAspectRatio) {\n            target.style.width = overflow ? 'auto' : '100%';\n            target.style.height = overflow ? '100%' : 'auto';\n          } else {\n            target.style.maxWidth = overflow ? `${viewportHeight / videoHeight * videoWidth}px` : null;\n            target.style.margin = overflow ? '0 auto' : null;\n          }\n        }; // Handle resizing\n\n\n        const resized = () => {\n          clearTimeout(timers.resized);\n          timers.resized = setTimeout(setGutter, 50);\n        };\n\n        on.call(player, elements.container, 'enterfullscreen exitfullscreen', event => {\n          const {\n            target\n          } = player.fullscreen; // Ignore events not from target\n\n          if (target !== elements.container) {\n            return;\n          } // If it's not an embed and no ratio specified\n\n\n          if (!player.isEmbed && is.empty(player.config.ratio)) {\n            return;\n          } // Set Vimeo gutter\n\n\n          setGutter(); // Watch for resizes\n\n          const method = event.type === 'enterfullscreen' ? on : off;\n          method.call(player, window, 'resize', resized);\n        });\n      });\n\n      _defineProperty$1(this, \"media\", () => {\n        const {\n          player\n        } = this;\n        const {\n          elements\n        } = player; // Time change on media\n\n        on.call(player, player.media, 'timeupdate seeking seeked', event => controls.timeUpdate.call(player, event)); // Display duration\n\n        on.call(player, player.media, 'durationchange loadeddata loadedmetadata', event => controls.durationUpdate.call(player, event)); // Handle the media finishing\n\n        on.call(player, player.media, 'ended', () => {\n          // Show poster on end\n          if (player.isHTML5 && player.isVideo && player.config.resetOnEnd) {\n            // Restart\n            player.restart(); // Call pause otherwise IE11 will start playing the video again\n\n            player.pause();\n          }\n        }); // Check for buffer progress\n\n        on.call(player, player.media, 'progress playing seeking seeked', event => controls.updateProgress.call(player, event)); // Handle volume changes\n\n        on.call(player, player.media, 'volumechange', event => controls.updateVolume.call(player, event)); // Handle play/pause\n\n        on.call(player, player.media, 'playing play pause ended emptied timeupdate', event => ui.checkPlaying.call(player, event)); // Loading state\n\n        on.call(player, player.media, 'waiting canplay seeked playing', event => ui.checkLoading.call(player, event)); // Click video\n\n        if (player.supported.ui && player.config.clickToPlay && !player.isAudio) {\n          // Re-fetch the wrapper\n          const wrapper = getElement.call(player, `.${player.config.classNames.video}`); // Bail if there's no wrapper (this should never happen)\n\n          if (!is.element(wrapper)) {\n            return;\n          } // On click play, pause or restart\n\n\n          on.call(player, elements.container, 'click', event => {\n            const targets = [elements.container, wrapper]; // Ignore if click if not container or in video wrapper\n\n            if (!targets.includes(event.target) && !wrapper.contains(event.target)) {\n              return;\n            } // Touch devices will just show controls (if hidden)\n\n\n            if (player.touch && player.config.hideControls) {\n              return;\n            }\n\n            if (player.ended) {\n              this.proxy(event, player.restart, 'restart');\n              this.proxy(event, () => {\n                silencePromise(player.play());\n              }, 'play');\n            } else {\n              this.proxy(event, () => {\n                silencePromise(player.togglePlay());\n              }, 'play');\n            }\n          });\n        } // Disable right click\n\n\n        if (player.supported.ui && player.config.disableContextMenu) {\n          on.call(player, elements.wrapper, 'contextmenu', event => {\n            event.preventDefault();\n          }, false);\n        } // Volume change\n\n\n        on.call(player, player.media, 'volumechange', () => {\n          // Save to storage\n          player.storage.set({\n            volume: player.volume,\n            muted: player.muted\n          });\n        }); // Speed change\n\n        on.call(player, player.media, 'ratechange', () => {\n          // Update UI\n          controls.updateSetting.call(player, 'speed'); // Save to storage\n\n          player.storage.set({\n            speed: player.speed\n          });\n        }); // Quality change\n\n        on.call(player, player.media, 'qualitychange', event => {\n          // Update UI\n          controls.updateSetting.call(player, 'quality', null, event.detail.quality);\n        }); // Update download link when ready and if quality changes\n\n        on.call(player, player.media, 'ready qualitychange', () => {\n          controls.setDownloadUrl.call(player);\n        }); // Proxy events to container\n        // Bubble up key events for Edge\n\n        const proxyEvents = player.config.events.concat(['keyup', 'keydown']).join(' ');\n        on.call(player, player.media, proxyEvents, event => {\n          let {\n            detail = {}\n          } = event; // Get error details from media\n\n          if (event.type === 'error') {\n            detail = player.media.error;\n          }\n\n          triggerEvent.call(player, elements.container, event.type, true, detail);\n        });\n      });\n\n      _defineProperty$1(this, \"proxy\", (event, defaultHandler, customHandlerKey) => {\n        const {\n          player\n        } = this;\n        const customHandler = player.config.listeners[customHandlerKey];\n        const hasCustomHandler = is.function(customHandler);\n        let returned = true; // Execute custom handler\n\n        if (hasCustomHandler) {\n          returned = customHandler.call(player, event);\n        } // Only call default handler if not prevented in custom handler\n\n\n        if (returned !== false && is.function(defaultHandler)) {\n          defaultHandler.call(player, event);\n        }\n      });\n\n      _defineProperty$1(this, \"bind\", (element, type, defaultHandler, customHandlerKey, passive = true) => {\n        const {\n          player\n        } = this;\n        const customHandler = player.config.listeners[customHandlerKey];\n        const hasCustomHandler = is.function(customHandler);\n        on.call(player, element, type, event => this.proxy(event, defaultHandler, customHandlerKey), passive && !hasCustomHandler);\n      });\n\n      _defineProperty$1(this, \"controls\", () => {\n        const {\n          player\n        } = this;\n        const {\n          elements\n        } = player; // IE doesn't support input event, so we fallback to change\n\n        const inputEvent = browser.isIE ? 'change' : 'input'; // Play/pause toggle\n\n        if (elements.buttons.play) {\n          Array.from(elements.buttons.play).forEach(button => {\n            this.bind(button, 'click', () => {\n              silencePromise(player.togglePlay());\n            }, 'play');\n          });\n        } // Pause\n\n\n        this.bind(elements.buttons.restart, 'click', player.restart, 'restart'); // Rewind\n\n        this.bind(elements.buttons.rewind, 'click', () => {\n          // Record seek time so we can prevent hiding controls for a few seconds after rewind\n          player.lastSeekTime = Date.now();\n          player.rewind();\n        }, 'rewind'); // Rewind\n\n        this.bind(elements.buttons.fastForward, 'click', () => {\n          // Record seek time so we can prevent hiding controls for a few seconds after fast forward\n          player.lastSeekTime = Date.now();\n          player.forward();\n        }, 'fastForward'); // Mute toggle\n\n        this.bind(elements.buttons.mute, 'click', () => {\n          player.muted = !player.muted;\n        }, 'mute'); // Captions toggle\n\n        this.bind(elements.buttons.captions, 'click', () => player.toggleCaptions()); // Download\n\n        this.bind(elements.buttons.download, 'click', () => {\n          triggerEvent.call(player, player.media, 'download');\n        }, 'download'); // Fullscreen toggle\n\n        this.bind(elements.buttons.fullscreen, 'click', () => {\n          player.fullscreen.toggle();\n        }, 'fullscreen'); // Picture-in-Picture\n\n        this.bind(elements.buttons.pip, 'click', () => {\n          player.pip = 'toggle';\n        }, 'pip'); // Airplay\n\n        this.bind(elements.buttons.airplay, 'click', player.airplay, 'airplay'); // Settings menu - click toggle\n\n        this.bind(elements.buttons.settings, 'click', event => {\n          // Prevent the document click listener closing the menu\n          event.stopPropagation();\n          event.preventDefault();\n          controls.toggleMenu.call(player, event);\n        }, null, false); // Can't be passive as we're preventing default\n        // Settings menu - keyboard toggle\n        // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus\n        // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143\n\n        this.bind(elements.buttons.settings, 'keyup', event => {\n          const code = event.which; // We only care about space and return\n\n          if (![13, 32].includes(code)) {\n            return;\n          } // Because return triggers a click anyway, all we need to do is set focus\n\n\n          if (code === 13) {\n            controls.focusFirstMenuItem.call(player, null, true);\n            return;\n          } // Prevent scroll\n\n\n          event.preventDefault(); // Prevent playing video (Firefox)\n\n          event.stopPropagation(); // Toggle menu\n\n          controls.toggleMenu.call(player, event);\n        }, null, false // Can't be passive as we're preventing default\n        ); // Escape closes menu\n\n        this.bind(elements.settings.menu, 'keydown', event => {\n          if (event.which === 27) {\n            controls.toggleMenu.call(player, event);\n          }\n        }); // Set range input alternative \"value\", which matches the tooltip time (#954)\n\n        this.bind(elements.inputs.seek, 'mousedown mousemove', event => {\n          const rect = elements.progress.getBoundingClientRect();\n          const percent = 100 / rect.width * (event.pageX - rect.left);\n          event.currentTarget.setAttribute('seek-value', percent);\n        }); // Pause while seeking\n\n        this.bind(elements.inputs.seek, 'mousedown mouseup keydown keyup touchstart touchend', event => {\n          const seek = event.currentTarget;\n          const code = event.keyCode ? event.keyCode : event.which;\n          const attribute = 'play-on-seeked';\n\n          if (is.keyboardEvent(event) && code !== 39 && code !== 37) {\n            return;\n          } // Record seek time so we can prevent hiding controls for a few seconds after seek\n\n\n          player.lastSeekTime = Date.now(); // Was playing before?\n\n          const play = seek.hasAttribute(attribute); // Done seeking\n\n          const done = ['mouseup', 'touchend', 'keyup'].includes(event.type); // If we're done seeking and it was playing, resume playback\n\n          if (play && done) {\n            seek.removeAttribute(attribute);\n            silencePromise(player.play());\n          } else if (!done && player.playing) {\n            seek.setAttribute(attribute, '');\n            player.pause();\n          }\n        }); // Fix range inputs on iOS\n        // Super weird iOS bug where after you interact with an <input type=\"range\">,\n        // it takes over further interactions on the page. This is a hack\n\n        if (browser.isIos) {\n          const inputs = getElements.call(player, 'input[type=\"range\"]');\n          Array.from(inputs).forEach(input => this.bind(input, inputEvent, event => repaint(event.target)));\n        } // Seek\n\n\n        this.bind(elements.inputs.seek, inputEvent, event => {\n          const seek = event.currentTarget; // If it exists, use seek-value instead of \"value\" for consistency with tooltip time (#954)\n\n          let seekTo = seek.getAttribute('seek-value');\n\n          if (is.empty(seekTo)) {\n            seekTo = seek.value;\n          }\n\n          seek.removeAttribute('seek-value');\n          player.currentTime = seekTo / seek.max * player.duration;\n        }, 'seek'); // Seek tooltip\n\n        this.bind(elements.progress, 'mouseenter mouseleave mousemove', event => controls.updateSeekTooltip.call(player, event)); // Preview thumbnails plugin\n        // TODO: Really need to work on some sort of plug-in wide event bus or pub-sub for this\n\n        this.bind(elements.progress, 'mousemove touchmove', event => {\n          const {\n            previewThumbnails\n          } = player;\n\n          if (previewThumbnails && previewThumbnails.loaded) {\n            previewThumbnails.startMove(event);\n          }\n        }); // Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering\n\n        this.bind(elements.progress, 'mouseleave touchend click', () => {\n          const {\n            previewThumbnails\n          } = player;\n\n          if (previewThumbnails && previewThumbnails.loaded) {\n            previewThumbnails.endMove(false, true);\n          }\n        }); // Show scrubbing preview\n\n        this.bind(elements.progress, 'mousedown touchstart', event => {\n          const {\n            previewThumbnails\n          } = player;\n\n          if (previewThumbnails && previewThumbnails.loaded) {\n            previewThumbnails.startScrubbing(event);\n          }\n        });\n        this.bind(elements.progress, 'mouseup touchend', event => {\n          const {\n            previewThumbnails\n          } = player;\n\n          if (previewThumbnails && previewThumbnails.loaded) {\n            previewThumbnails.endScrubbing(event);\n          }\n        }); // Polyfill for lower fill in <input type=\"range\"> for webkit\n\n        if (browser.isWebkit) {\n          Array.from(getElements.call(player, 'input[type=\"range\"]')).forEach(element => {\n            this.bind(element, 'input', event => controls.updateRangeFill.call(player, event.target));\n          });\n        } // Current time invert\n        // Only if one time element is used for both currentTime and duration\n\n\n        if (player.config.toggleInvert && !is.element(elements.display.duration)) {\n          this.bind(elements.display.currentTime, 'click', () => {\n            // Do nothing if we're at the start\n            if (player.currentTime === 0) {\n              return;\n            }\n\n            player.config.invertTime = !player.config.invertTime;\n            controls.timeUpdate.call(player);\n          });\n        } // Volume\n\n\n        this.bind(elements.inputs.volume, inputEvent, event => {\n          player.volume = event.target.value;\n        }, 'volume'); // Update controls.hover state (used for ui.toggleControls to avoid hiding when interacting)\n\n        this.bind(elements.controls, 'mouseenter mouseleave', event => {\n          elements.controls.hover = !player.touch && event.type === 'mouseenter';\n        }); // Also update controls.hover state for any non-player children of fullscreen element (as above)\n\n        if (elements.fullscreen) {\n          Array.from(elements.fullscreen.children).filter(c => !c.contains(elements.container)).forEach(child => {\n            this.bind(child, 'mouseenter mouseleave', event => {\n              if (elements.controls) {\n                elements.controls.hover = !player.touch && event.type === 'mouseenter';\n              }\n            });\n          });\n        } // Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting)\n\n\n        this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', event => {\n          elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type);\n        }); // Show controls when they receive focus (e.g., when using keyboard tab key)\n\n        this.bind(elements.controls, 'focusin', () => {\n          const {\n            config,\n            timers\n          } = player; // Skip transition to prevent focus from scrolling the parent element\n\n          toggleClass(elements.controls, config.classNames.noTransition, true); // Toggle\n\n          ui.toggleControls.call(player, true); // Restore transition\n\n          setTimeout(() => {\n            toggleClass(elements.controls, config.classNames.noTransition, false);\n          }, 0); // Delay a little more for mouse users\n\n          const delay = this.touch ? 3000 : 4000; // Clear timer\n\n          clearTimeout(timers.controls); // Hide again after delay\n\n          timers.controls = setTimeout(() => ui.toggleControls.call(player, false), delay);\n        }); // Mouse wheel for volume\n\n        this.bind(elements.inputs.volume, 'wheel', event => {\n          // Detect \"natural\" scroll - suppored on OS X Safari only\n          // Other browsers on OS X will be inverted until support improves\n          const inverted = event.webkitDirectionInvertedFromDevice; // Get delta from event. Invert if `inverted` is true\n\n          const [x, y] = [event.deltaX, -event.deltaY].map(value => inverted ? -value : value); // Using the biggest delta, normalize to 1 or -1 (or 0 if no delta)\n\n          const direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y); // Change the volume by 2%\n\n          player.increaseVolume(direction / 50); // Don't break page scrolling at max and min\n\n          const {\n            volume\n          } = player.media;\n\n          if (direction === 1 && volume < 1 || direction === -1 && volume > 0) {\n            event.preventDefault();\n          }\n        }, 'volume', false);\n      });\n\n      this.player = _player;\n      this.lastKey = null;\n      this.focusTimer = null;\n      this.lastKeyDown = null;\n      this.handleKey = this.handleKey.bind(this);\n      this.toggleMenu = this.toggleMenu.bind(this);\n      this.setTabFocus = this.setTabFocus.bind(this);\n      this.firstTouch = this.firstTouch.bind(this);\n    } // Handle key presses\n\n\n    handleKey(event) {\n      const {\n        player\n      } = this;\n      const {\n        elements\n      } = player;\n      const code = event.keyCode ? event.keyCode : event.which;\n      const pressed = event.type === 'keydown';\n      const repeat = pressed && code === this.lastKey; // Bail if a modifier key is set\n\n      if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {\n        return;\n      } // If the event is bubbled from the media element\n      // Firefox doesn't get the keycode for whatever reason\n\n\n      if (!is.number(code)) {\n        return;\n      } // Seek by the number keys\n\n\n      const seekByKey = () => {\n        // Divide the max duration into 10th's and times by the number value\n        player.currentTime = player.duration / 10 * (code - 48);\n      }; // Handle the key on keydown\n      // Reset on keyup\n\n\n      if (pressed) {\n        // Check focused element\n        // and if the focused element is not editable (e.g. text input)\n        // and any that accept key input http://webaim.org/techniques/keyboard/\n        const focused = document.activeElement;\n\n        if (is.element(focused)) {\n          const {\n            editable\n          } = player.config.selectors;\n          const {\n            seek\n          } = elements.inputs;\n\n          if (focused !== seek && matches(focused, editable)) {\n            return;\n          }\n\n          if (event.which === 32 && matches(focused, 'button, [role^=\"menuitem\"]')) {\n            return;\n          }\n        } // Which keycodes should we prevent default\n\n\n        const preventDefault = [32, 37, 38, 39, 40, 48, 49, 50, 51, 52, 53, 54, 56, 57, 67, 70, 73, 75, 76, 77, 79]; // If the code is found prevent default (e.g. prevent scrolling for arrows)\n\n        if (preventDefault.includes(code)) {\n          event.preventDefault();\n          event.stopPropagation();\n        }\n\n        switch (code) {\n          case 48:\n          case 49:\n          case 50:\n          case 51:\n          case 52:\n          case 53:\n          case 54:\n          case 55:\n          case 56:\n          case 57:\n            // 0-9\n            if (!repeat) {\n              seekByKey();\n            }\n\n            break;\n\n          case 32:\n          case 75:\n            // Space and K key\n            if (!repeat) {\n              silencePromise(player.togglePlay());\n            }\n\n            break;\n\n          case 38:\n            // Arrow up\n            player.increaseVolume(0.1);\n            break;\n\n          case 40:\n            // Arrow down\n            player.decreaseVolume(0.1);\n            break;\n\n          case 77:\n            // M key\n            if (!repeat) {\n              player.muted = !player.muted;\n            }\n\n            break;\n\n          case 39:\n            // Arrow forward\n            player.forward();\n            break;\n\n          case 37:\n            // Arrow back\n            player.rewind();\n            break;\n\n          case 70:\n            // F key\n            player.fullscreen.toggle();\n            break;\n\n          case 67:\n            // C key\n            if (!repeat) {\n              player.toggleCaptions();\n            }\n\n            break;\n\n          case 76:\n            // L key\n            player.loop = !player.loop;\n            break;\n        } // Escape is handle natively when in full screen\n        // So we only need to worry about non native\n\n\n        if (code === 27 && !player.fullscreen.usingNative && player.fullscreen.active) {\n          player.fullscreen.toggle();\n        } // Store last code for next cycle\n\n\n        this.lastKey = code;\n      } else {\n        this.lastKey = null;\n      }\n    } // Toggle menu\n\n\n    toggleMenu(event) {\n      controls.toggleMenu.call(this.player, event);\n    } // Device is touch enabled\n\n\n  }\n\n  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};\n\n  function createCommonjsModule(fn, module) {\n  \treturn module = { exports: {} }, fn(module, module.exports), module.exports;\n  }\n\n  var loadjs_umd = createCommonjsModule(function (module, exports) {\n    (function (root, factory) {\n      {\n        module.exports = factory();\n      }\n    })(commonjsGlobal, function () {\n      /**\n       * Global dependencies.\n       * @global {Object} document - DOM\n       */\n      var devnull = function () {},\n          bundleIdCache = {},\n          bundleResultCache = {},\n          bundleCallbackQueue = {};\n      /**\n       * Subscribe to bundle load event.\n       * @param {string[]} bundleIds - Bundle ids\n       * @param {Function} callbackFn - The callback function\n       */\n\n\n      function subscribe(bundleIds, callbackFn) {\n        // listify\n        bundleIds = bundleIds.push ? bundleIds : [bundleIds];\n        var depsNotFound = [],\n            i = bundleIds.length,\n            numWaiting = i,\n            fn,\n            bundleId,\n            r,\n            q; // define callback function\n\n        fn = function (bundleId, pathsNotFound) {\n          if (pathsNotFound.length) depsNotFound.push(bundleId);\n          numWaiting--;\n          if (!numWaiting) callbackFn(depsNotFound);\n        }; // register callback\n\n\n        while (i--) {\n          bundleId = bundleIds[i]; // execute callback if in result cache\n\n          r = bundleResultCache[bundleId];\n\n          if (r) {\n            fn(bundleId, r);\n            continue;\n          } // add to callback queue\n\n\n          q = bundleCallbackQueue[bundleId] = bundleCallbackQueue[bundleId] || [];\n          q.push(fn);\n        }\n      }\n      /**\n       * Publish bundle load event.\n       * @param {string} bundleId - Bundle id\n       * @param {string[]} pathsNotFound - List of files not found\n       */\n\n\n      function publish(bundleId, pathsNotFound) {\n        // exit if id isn't defined\n        if (!bundleId) return;\n        var q = bundleCallbackQueue[bundleId]; // cache result\n\n        bundleResultCache[bundleId] = pathsNotFound; // exit if queue is empty\n\n        if (!q) return; // empty callback queue\n\n        while (q.length) {\n          q[0](bundleId, pathsNotFound);\n          q.splice(0, 1);\n        }\n      }\n      /**\n       * Execute callbacks.\n       * @param {Object or Function} args - The callback args\n       * @param {string[]} depsNotFound - List of dependencies not found\n       */\n\n\n      function executeCallbacks(args, depsNotFound) {\n        // accept function as argument\n        if (args.call) args = {\n          success: args\n        }; // success and error callbacks\n\n        if (depsNotFound.length) (args.error || devnull)(depsNotFound);else (args.success || devnull)(args);\n      }\n      /**\n       * Load individual file.\n       * @param {string} path - The file path\n       * @param {Function} callbackFn - The callback function\n       */\n\n\n      function loadFile(path, callbackFn, args, numTries) {\n        var doc = document,\n            async = args.async,\n            maxTries = (args.numRetries || 0) + 1,\n            beforeCallbackFn = args.before || devnull,\n            pathname = path.replace(/[\\?|#].*$/, ''),\n            pathStripped = path.replace(/^(css|img)!/, ''),\n            isLegacyIECss,\n            e;\n        numTries = numTries || 0;\n\n        if (/(^css!|\\.css$)/.test(pathname)) {\n          // css\n          e = doc.createElement('link');\n          e.rel = 'stylesheet';\n          e.href = pathStripped; // tag IE9+\n\n          isLegacyIECss = 'hideFocus' in e; // use preload in IE Edge (to detect load errors)\n\n          if (isLegacyIECss && e.relList) {\n            isLegacyIECss = 0;\n            e.rel = 'preload';\n            e.as = 'style';\n          }\n        } else if (/(^img!|\\.(png|gif|jpg|svg|webp)$)/.test(pathname)) {\n          // image\n          e = doc.createElement('img');\n          e.src = pathStripped;\n        } else {\n          // javascript\n          e = doc.createElement('script');\n          e.src = path;\n          e.async = async === undefined ? true : async;\n        }\n\n        e.onload = e.onerror = e.onbeforeload = function (ev) {\n          var result = ev.type[0]; // treat empty stylesheets as failures to get around lack of onerror\n          // support in IE9-11\n\n          if (isLegacyIECss) {\n            try {\n              if (!e.sheet.cssText.length) result = 'e';\n            } catch (x) {\n              // sheets objects created from load errors don't allow access to\n              // `cssText` (unless error is Code:18 SecurityError)\n              if (x.code != 18) result = 'e';\n            }\n          } // handle retries in case of load failure\n\n\n          if (result == 'e') {\n            // increment counter\n            numTries += 1; // exit function and try again\n\n            if (numTries < maxTries) {\n              return loadFile(path, callbackFn, args, numTries);\n            }\n          } else if (e.rel == 'preload' && e.as == 'style') {\n            // activate preloaded stylesheets\n            return e.rel = 'stylesheet'; // jshint ignore:line\n          } // execute callback\n\n\n          callbackFn(path, result, ev.defaultPrevented);\n        }; // add to document (unless callback returns `false`)\n\n\n        if (beforeCallbackFn(path, e) !== false) doc.head.appendChild(e);\n      }\n      /**\n       * Load multiple files.\n       * @param {string[]} paths - The file paths\n       * @param {Function} callbackFn - The callback function\n       */\n\n\n      function loadFiles(paths, callbackFn, args) {\n        // listify paths\n        paths = paths.push ? paths : [paths];\n        var numWaiting = paths.length,\n            x = numWaiting,\n            pathsNotFound = [],\n            fn,\n            i; // define callback function\n\n        fn = function (path, result, defaultPrevented) {\n          // handle error\n          if (result == 'e') pathsNotFound.push(path); // handle beforeload event. If defaultPrevented then that means the load\n          // will be blocked (ex. Ghostery/ABP on Safari)\n\n          if (result == 'b') {\n            if (defaultPrevented) pathsNotFound.push(path);else return;\n          }\n\n          numWaiting--;\n          if (!numWaiting) callbackFn(pathsNotFound);\n        }; // load scripts\n\n\n        for (i = 0; i < x; i++) loadFile(paths[i], fn, args);\n      }\n      /**\n       * Initiate script load and register bundle.\n       * @param {(string|string[])} paths - The file paths\n       * @param {(string|Function|Object)} [arg1] - The (1) bundleId or (2) success\n       *   callback or (3) object literal with success/error arguments, numRetries,\n       *   etc.\n       * @param {(Function|Object)} [arg2] - The (1) success callback or (2) object\n       *   literal with success/error arguments, numRetries, etc.\n       */\n\n\n      function loadjs(paths, arg1, arg2) {\n        var bundleId, args; // bundleId (if string)\n\n        if (arg1 && arg1.trim) bundleId = arg1; // args (default is {})\n\n        args = (bundleId ? arg2 : arg1) || {}; // throw error if bundle is already defined\n\n        if (bundleId) {\n          if (bundleId in bundleIdCache) {\n            throw \"LoadJS\";\n          } else {\n            bundleIdCache[bundleId] = true;\n          }\n        }\n\n        function loadFn(resolve, reject) {\n          loadFiles(paths, function (pathsNotFound) {\n            // execute callbacks\n            executeCallbacks(args, pathsNotFound); // resolve Promise\n\n            if (resolve) {\n              executeCallbacks({\n                success: resolve,\n                error: reject\n              }, pathsNotFound);\n            } // publish bundle load event\n\n\n            publish(bundleId, pathsNotFound);\n          }, args);\n        }\n\n        if (args.returnPromise) return new Promise(loadFn);else loadFn();\n      }\n      /**\n       * Execute callbacks when dependencies have been satisfied.\n       * @param {(string|string[])} deps - List of bundle ids\n       * @param {Object} args - success/error arguments\n       */\n\n\n      loadjs.ready = function ready(deps, args) {\n        // subscribe to bundle load event\n        subscribe(deps, function (depsNotFound) {\n          // execute callbacks\n          executeCallbacks(args, depsNotFound);\n        });\n        return loadjs;\n      };\n      /**\n       * Manually satisfy bundle dependencies.\n       * @param {string} bundleId - The bundle id\n       */\n\n\n      loadjs.done = function done(bundleId) {\n        publish(bundleId, []);\n      };\n      /**\n       * Reset loadjs dependencies statuses\n       */\n\n\n      loadjs.reset = function reset() {\n        bundleIdCache = {};\n        bundleResultCache = {};\n        bundleCallbackQueue = {};\n      };\n      /**\n       * Determine if bundle has already been defined\n       * @param String} bundleId - The bundle id\n       */\n\n\n      loadjs.isDefined = function isDefined(bundleId) {\n        return bundleId in bundleIdCache;\n      }; // export\n\n\n      return loadjs;\n    });\n  });\n\n  // ==========================================================================\n  function loadScript(url) {\n    return new Promise((resolve, reject) => {\n      loadjs_umd(url, {\n        success: resolve,\n        error: reject\n      });\n    });\n  }\n\n  // ==========================================================================\n\n  function parseId$1(url) {\n    if (is.empty(url)) {\n      return null;\n    }\n\n    if (is.number(Number(url))) {\n      return url;\n    }\n\n    const regex = /^.*(vimeo.com\\/|video\\/)(\\d+).*/;\n    return url.match(regex) ? RegExp.$2 : url;\n  } // Try to extract a hash for private videos from the URL\n\n\n  function parseHash(url) {\n    /* This regex matches a hexadecimal hash if given in any of these forms:\n     *  - [https://player.]vimeo.com/video/{id}/{hash}[?params]\n     *  - [https://player.]vimeo.com/video/{id}?h={hash}[&params]\n     *  - [https://player.]vimeo.com/video/{id}?[params]&h={hash}\n     *  - video/{id}/{hash}\n     * If matched, the hash is available in the named group `hash`\n     */\n    const regex = /^.*(?:vimeo.com\\/|video\\/)(?:\\d+)(?:\\?.*&*h=|\\/)+(?<hash>[\\d,a-f]+)/;\n    const found = url.match(regex);\n    return found ? found.groups.hash : null;\n  } // Set playback state and trigger change (only on actual change)\n\n\n  function assurePlaybackState$1(play) {\n    if (play && !this.embed.hasPlayed) {\n      this.embed.hasPlayed = true;\n    }\n\n    if (this.media.paused === play) {\n      this.media.paused = !play;\n      triggerEvent.call(this, this.media, play ? 'play' : 'pause');\n    }\n  }\n\n  const vimeo = {\n    setup() {\n      const player = this; // Add embed class for responsive\n\n      toggleClass(player.elements.wrapper, player.config.classNames.embed, true); // Set speed options from config\n\n      player.options.speed = player.config.speed.options; // Set intial ratio\n\n      setAspectRatio.call(player); // Load the SDK if not already\n\n      if (!is.object(window.Vimeo)) {\n        loadScript(player.config.urls.vimeo.sdk).then(() => {\n          vimeo.ready.call(player);\n        }).catch(error => {\n          player.debug.warn('Vimeo SDK (player.js) failed to load', error);\n        });\n      } else {\n        vimeo.ready.call(player);\n      }\n    },\n\n    // API Ready\n    ready() {\n      const player = this;\n      const config = player.config.vimeo;\n      const {\n        premium,\n        referrerPolicy,\n        ...frameParams\n      } = config; // Get the source URL or ID\n\n      let source = player.media.getAttribute('src');\n      let hash = ''; // Get from <div> if needed\n\n      if (is.empty(source)) {\n        source = player.media.getAttribute(player.config.attributes.embed.id); // hash can also be set as attribute on the <div>\n\n        hash = player.media.getAttribute(player.config.attributes.embed.hash);\n      } else {\n        hash = parseHash(source);\n      }\n\n      const hashParam = hash ? {\n        h: hash\n      } : {}; // If the owner has a pro or premium account then we can hide controls etc\n\n      if (premium) {\n        Object.assign(frameParams, {\n          controls: false,\n          sidedock: false\n        });\n      } // Get Vimeo params for the iframe\n\n\n      const params = buildUrlParams({\n        loop: player.config.loop.active,\n        autoplay: player.autoplay,\n        muted: player.muted,\n        gesture: 'media',\n        playsinline: !this.config.fullscreen.iosNative,\n        // hash has to be added to iframe-URL\n        ...hashParam,\n        ...frameParams\n      });\n      const id = parseId$1(source); // Build an iframe\n\n      const iframe = createElement('iframe');\n      const src = format(player.config.urls.vimeo.iframe, id, params);\n      iframe.setAttribute('src', src);\n      iframe.setAttribute('allowfullscreen', '');\n      iframe.setAttribute('allow', ['autoplay', 'fullscreen', 'picture-in-picture', 'encrypted-media', 'accelerometer', 'gyroscope'].join('; ')); // Set the referrer policy if required\n\n      if (!is.empty(referrerPolicy)) {\n        iframe.setAttribute('referrerPolicy', referrerPolicy);\n      } // Inject the package\n\n\n      if (premium || !config.customControls) {\n        iframe.setAttribute('data-poster', player.poster);\n        player.media = replaceElement(iframe, player.media);\n      } else {\n        const wrapper = createElement('div', {\n          class: player.config.classNames.embedContainer,\n          'data-poster': player.poster\n        });\n        wrapper.appendChild(iframe);\n        player.media = replaceElement(wrapper, player.media);\n      } // Get poster image\n\n\n      if (!config.customControls) {\n        fetch(format(player.config.urls.vimeo.api, src)).then(response => {\n          if (is.empty(response) || !response.thumbnail_url) {\n            return;\n          } // Set and show poster\n\n\n          ui.setPoster.call(player, response.thumbnail_url).catch(() => {});\n        });\n      } // Setup instance\n      // https://github.com/vimeo/player.js\n\n\n      player.embed = new window.Vimeo.Player(iframe, {\n        autopause: player.config.autopause,\n        muted: player.muted\n      });\n      player.media.paused = true;\n      player.media.currentTime = 0; // Disable native text track rendering\n\n      if (player.supported.ui) {\n        player.embed.disableTextTrack();\n      } // Create a faux HTML5 API using the Vimeo API\n\n\n      player.media.play = () => {\n        assurePlaybackState$1.call(player, true);\n        return player.embed.play();\n      };\n\n      player.media.pause = () => {\n        assurePlaybackState$1.call(player, false);\n        return player.embed.pause();\n      };\n\n      player.media.stop = () => {\n        player.pause();\n        player.currentTime = 0;\n      }; // Seeking\n\n\n      let {\n        currentTime\n      } = player.media;\n      Object.defineProperty(player.media, 'currentTime', {\n        get() {\n          return currentTime;\n        },\n\n        set(time) {\n          // Vimeo will automatically play on seek if the video hasn't been played before\n          // Get current paused state and volume etc\n          const {\n            embed,\n            media,\n            paused,\n            volume\n          } = player;\n          const restorePause = paused && !embed.hasPlayed; // Set seeking state and trigger event\n\n          media.seeking = true;\n          triggerEvent.call(player, media, 'seeking'); // If paused, mute until seek is complete\n\n          Promise.resolve(restorePause && embed.setVolume(0)) // Seek\n          .then(() => embed.setCurrentTime(time)) // Restore paused\n          .then(() => restorePause && embed.pause()) // Restore volume\n          .then(() => restorePause && embed.setVolume(volume)).catch(() => {// Do nothing\n          });\n        }\n\n      }); // Playback speed\n\n      let speed = player.config.speed.selected;\n      Object.defineProperty(player.media, 'playbackRate', {\n        get() {\n          return speed;\n        },\n\n        set(input) {\n          player.embed.setPlaybackRate(input).then(() => {\n            speed = input;\n            triggerEvent.call(player, player.media, 'ratechange');\n          }).catch(() => {\n            // Cannot set Playback Rate, Video is probably not on Pro account\n            player.options.speed = [1];\n          });\n        }\n\n      }); // Volume\n\n      let {\n        volume\n      } = player.config;\n      Object.defineProperty(player.media, 'volume', {\n        get() {\n          return volume;\n        },\n\n        set(input) {\n          player.embed.setVolume(input).then(() => {\n            volume = input;\n            triggerEvent.call(player, player.media, 'volumechange');\n          });\n        }\n\n      }); // Muted\n\n      let {\n        muted\n      } = player.config;\n      Object.defineProperty(player.media, 'muted', {\n        get() {\n          return muted;\n        },\n\n        set(input) {\n          const toggle = is.boolean(input) ? input : false;\n          player.embed.setVolume(toggle ? 0 : player.config.volume).then(() => {\n            muted = toggle;\n            triggerEvent.call(player, player.media, 'volumechange');\n          });\n        }\n\n      }); // Loop\n\n      let {\n        loop\n      } = player.config;\n      Object.defineProperty(player.media, 'loop', {\n        get() {\n          return loop;\n        },\n\n        set(input) {\n          const toggle = is.boolean(input) ? input : player.config.loop.active;\n          player.embed.setLoop(toggle).then(() => {\n            loop = toggle;\n          });\n        }\n\n      }); // Source\n\n      let currentSrc;\n      player.embed.getVideoUrl().then(value => {\n        currentSrc = value;\n        controls.setDownloadUrl.call(player);\n      }).catch(error => {\n        this.debug.warn(error);\n      });\n      Object.defineProperty(player.media, 'currentSrc', {\n        get() {\n          return currentSrc;\n        }\n\n      }); // Ended\n\n      Object.defineProperty(player.media, 'ended', {\n        get() {\n          return player.currentTime === player.duration;\n        }\n\n      }); // Set aspect ratio based on video size\n\n      Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then(dimensions => {\n        const [width, height] = dimensions;\n        player.embed.ratio = roundAspectRatio(width, height);\n        setAspectRatio.call(this);\n      }); // Set autopause\n\n      player.embed.setAutopause(player.config.autopause).then(state => {\n        player.config.autopause = state;\n      }); // Get title\n\n      player.embed.getVideoTitle().then(title => {\n        player.config.title = title;\n        ui.setTitle.call(this);\n      }); // Get current time\n\n      player.embed.getCurrentTime().then(value => {\n        currentTime = value;\n        triggerEvent.call(player, player.media, 'timeupdate');\n      }); // Get duration\n\n      player.embed.getDuration().then(value => {\n        player.media.duration = value;\n        triggerEvent.call(player, player.media, 'durationchange');\n      }); // Get captions\n\n      player.embed.getTextTracks().then(tracks => {\n        player.media.textTracks = tracks;\n        captions.setup.call(player);\n      });\n      player.embed.on('cuechange', ({\n        cues = []\n      }) => {\n        const strippedCues = cues.map(cue => stripHTML(cue.text));\n        captions.updateCues.call(player, strippedCues);\n      });\n      player.embed.on('loaded', () => {\n        // Assure state and events are updated on autoplay\n        player.embed.getPaused().then(paused => {\n          assurePlaybackState$1.call(player, !paused);\n\n          if (!paused) {\n            triggerEvent.call(player, player.media, 'playing');\n          }\n        });\n\n        if (is.element(player.embed.element) && player.supported.ui) {\n          const frame = player.embed.element; // Fix keyboard focus issues\n          // https://github.com/sampotts/plyr/issues/317\n\n          frame.setAttribute('tabindex', -1);\n        }\n      });\n      player.embed.on('bufferstart', () => {\n        triggerEvent.call(player, player.media, 'waiting');\n      });\n      player.embed.on('bufferend', () => {\n        triggerEvent.call(player, player.media, 'playing');\n      });\n      player.embed.on('play', () => {\n        assurePlaybackState$1.call(player, true);\n        triggerEvent.call(player, player.media, 'playing');\n      });\n      player.embed.on('pause', () => {\n        assurePlaybackState$1.call(player, false);\n      });\n      player.embed.on('timeupdate', data => {\n        player.media.seeking = false;\n        currentTime = data.seconds;\n        triggerEvent.call(player, player.media, 'timeupdate');\n      });\n      player.embed.on('progress', data => {\n        player.media.buffered = data.percent;\n        triggerEvent.call(player, player.media, 'progress'); // Check all loaded\n\n        if (parseInt(data.percent, 10) === 1) {\n          triggerEvent.call(player, player.media, 'canplaythrough');\n        } // Get duration as if we do it before load, it gives an incorrect value\n        // https://github.com/sampotts/plyr/issues/891\n\n\n        player.embed.getDuration().then(value => {\n          if (value !== player.media.duration) {\n            player.media.duration = value;\n            triggerEvent.call(player, player.media, 'durationchange');\n          }\n        });\n      });\n      player.embed.on('seeked', () => {\n        player.media.seeking = false;\n        triggerEvent.call(player, player.media, 'seeked');\n      });\n      player.embed.on('ended', () => {\n        player.media.paused = true;\n        triggerEvent.call(player, player.media, 'ended');\n      });\n      player.embed.on('error', detail => {\n        player.media.error = detail;\n        triggerEvent.call(player, player.media, 'error');\n      }); // Rebuild UI\n\n      if (config.customControls) {\n        setTimeout(() => ui.build.call(player), 0);\n      }\n    }\n\n  };\n\n  // ==========================================================================\n\n  function parseId(url) {\n    if (is.empty(url)) {\n      return null;\n    }\n\n    const regex = /^.*(youtu.be\\/|v\\/|u\\/\\w\\/|embed\\/|watch\\?v=|&v=)([^#&?]*).*/;\n    return url.match(regex) ? RegExp.$2 : url;\n  } // Set playback state and trigger change (only on actual change)\n\n\n  function assurePlaybackState(play) {\n    if (play && !this.embed.hasPlayed) {\n      this.embed.hasPlayed = true;\n    }\n\n    if (this.media.paused === play) {\n      this.media.paused = !play;\n      triggerEvent.call(this, this.media, play ? 'play' : 'pause');\n    }\n  }\n\n  function getHost(config) {\n    if (config.noCookie) {\n      return 'https://www.youtube-nocookie.com';\n    }\n\n    if (window.location.protocol === 'http:') {\n      return 'http://www.youtube.com';\n    } // Use YouTube's default\n\n\n    return undefined;\n  }\n\n  const youtube = {\n    setup() {\n      // Add embed class for responsive\n      toggleClass(this.elements.wrapper, this.config.classNames.embed, true); // Setup API\n\n      if (is.object(window.YT) && is.function(window.YT.Player)) {\n        youtube.ready.call(this);\n      } else {\n        // Reference current global callback\n        const callback = window.onYouTubeIframeAPIReady; // Set callback to process queue\n\n        window.onYouTubeIframeAPIReady = () => {\n          // Call global callback if set\n          if (is.function(callback)) {\n            callback();\n          }\n\n          youtube.ready.call(this);\n        }; // Load the SDK\n\n\n        loadScript(this.config.urls.youtube.sdk).catch(error => {\n          this.debug.warn('YouTube API failed to load', error);\n        });\n      }\n    },\n\n    // Get the media title\n    getTitle(videoId) {\n      const url = format(this.config.urls.youtube.api, videoId);\n      fetch(url).then(data => {\n        if (is.object(data)) {\n          const {\n            title,\n            height,\n            width\n          } = data; // Set title\n\n          this.config.title = title;\n          ui.setTitle.call(this); // Set aspect ratio\n\n          this.embed.ratio = roundAspectRatio(width, height);\n        }\n\n        setAspectRatio.call(this);\n      }).catch(() => {\n        // Set aspect ratio\n        setAspectRatio.call(this);\n      });\n    },\n\n    // API ready\n    ready() {\n      const player = this;\n      const config = player.config.youtube; // Ignore already setup (race condition)\n\n      const currentId = player.media && player.media.getAttribute('id');\n\n      if (!is.empty(currentId) && currentId.startsWith('youtube-')) {\n        return;\n      } // Get the source URL or ID\n\n\n      let source = player.media.getAttribute('src'); // Get from <div> if needed\n\n      if (is.empty(source)) {\n        source = player.media.getAttribute(this.config.attributes.embed.id);\n      } // Replace the <iframe> with a <div> due to YouTube API issues\n\n\n      const videoId = parseId(source);\n      const id = generateId(player.provider); // Replace media element\n\n      const container = createElement('div', {\n        id,\n        'data-poster': config.customControls ? player.poster : undefined\n      });\n      player.media = replaceElement(container, player.media); // Only load the poster when using custom controls\n\n      if (config.customControls) {\n        const posterSrc = s => `https://i.ytimg.com/vi/${videoId}/${s}default.jpg`; // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide)\n\n\n        loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded\n        .catch(() => loadImage(posterSrc('sd'), 121)) // 480p padded 4:3\n        .catch(() => loadImage(posterSrc('hq'))) // 360p padded 4:3. Always exists\n        .then(image => ui.setPoster.call(player, image.src)).then(src => {\n          // If the image is padded, use background-size \"cover\" instead (like youtube does too with their posters)\n          if (!src.includes('maxres')) {\n            player.elements.poster.style.backgroundSize = 'cover';\n          }\n        }).catch(() => {});\n      } // Setup instance\n      // https://developers.google.com/youtube/iframe_api_reference\n\n\n      player.embed = new window.YT.Player(player.media, {\n        videoId,\n        host: getHost(config),\n        playerVars: extend({}, {\n          // Autoplay\n          autoplay: player.config.autoplay ? 1 : 0,\n          // iframe interface language\n          hl: player.config.hl,\n          // Only show controls if not fully supported or opted out\n          controls: player.supported.ui && config.customControls ? 0 : 1,\n          // Disable keyboard as we handle it\n          disablekb: 1,\n          // Allow iOS inline playback\n          playsinline: !player.config.fullscreen.iosNative ? 1 : 0,\n          // Captions are flaky on YouTube\n          cc_load_policy: player.captions.active ? 1 : 0,\n          cc_lang_pref: player.config.captions.language,\n          // Tracking for stats\n          widget_referrer: window ? window.location.href : null\n        }, config),\n        events: {\n          onError(event) {\n            // YouTube may fire onError twice, so only handle it once\n            if (!player.media.error) {\n              const code = event.data; // Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError\n\n              const message = {\n                2: 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.',\n                5: 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.',\n                100: 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.',\n                101: 'The owner of the requested video does not allow it to be played in embedded players.',\n                150: 'The owner of the requested video does not allow it to be played in embedded players.'\n              }[code] || 'An unknown error occured';\n              player.media.error = {\n                code,\n                message\n              };\n              triggerEvent.call(player, player.media, 'error');\n            }\n          },\n\n          onPlaybackRateChange(event) {\n            // Get the instance\n            const instance = event.target; // Get current speed\n\n            player.media.playbackRate = instance.getPlaybackRate();\n            triggerEvent.call(player, player.media, 'ratechange');\n          },\n\n          onReady(event) {\n            // Bail if onReady has already been called. See issue #1108\n            if (is.function(player.media.play)) {\n              return;\n            } // Get the instance\n\n\n            const instance = event.target; // Get the title\n\n            youtube.getTitle.call(player, videoId); // Create a faux HTML5 API using the YouTube API\n\n            player.media.play = () => {\n              assurePlaybackState.call(player, true);\n              instance.playVideo();\n            };\n\n            player.media.pause = () => {\n              assurePlaybackState.call(player, false);\n              instance.pauseVideo();\n            };\n\n            player.media.stop = () => {\n              instance.stopVideo();\n            };\n\n            player.media.duration = instance.getDuration();\n            player.media.paused = true; // Seeking\n\n            player.media.currentTime = 0;\n            Object.defineProperty(player.media, 'currentTime', {\n              get() {\n                return Number(instance.getCurrentTime());\n              },\n\n              set(time) {\n                // If paused and never played, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet).\n                if (player.paused && !player.embed.hasPlayed) {\n                  player.embed.mute();\n                } // Set seeking state and trigger event\n\n\n                player.media.seeking = true;\n                triggerEvent.call(player, player.media, 'seeking'); // Seek after events sent\n\n                instance.seekTo(time);\n              }\n\n            }); // Playback speed\n\n            Object.defineProperty(player.media, 'playbackRate', {\n              get() {\n                return instance.getPlaybackRate();\n              },\n\n              set(input) {\n                instance.setPlaybackRate(input);\n              }\n\n            }); // Volume\n\n            let {\n              volume\n            } = player.config;\n            Object.defineProperty(player.media, 'volume', {\n              get() {\n                return volume;\n              },\n\n              set(input) {\n                volume = input;\n                instance.setVolume(volume * 100);\n                triggerEvent.call(player, player.media, 'volumechange');\n              }\n\n            }); // Muted\n\n            let {\n              muted\n            } = player.config;\n            Object.defineProperty(player.media, 'muted', {\n              get() {\n                return muted;\n              },\n\n              set(input) {\n                const toggle = is.boolean(input) ? input : muted;\n                muted = toggle;\n                instance[toggle ? 'mute' : 'unMute']();\n                instance.setVolume(volume * 100);\n                triggerEvent.call(player, player.media, 'volumechange');\n              }\n\n            }); // Source\n\n            Object.defineProperty(player.media, 'currentSrc', {\n              get() {\n                return instance.getVideoUrl();\n              }\n\n            }); // Ended\n\n            Object.defineProperty(player.media, 'ended', {\n              get() {\n                return player.currentTime === player.duration;\n              }\n\n            }); // Get available speeds\n\n            const speeds = instance.getAvailablePlaybackRates(); // Filter based on config\n\n            player.options.speed = speeds.filter(s => player.config.speed.options.includes(s)); // Set the tabindex to avoid focus entering iframe\n\n            if (player.supported.ui && config.customControls) {\n              player.media.setAttribute('tabindex', -1);\n            }\n\n            triggerEvent.call(player, player.media, 'timeupdate');\n            triggerEvent.call(player, player.media, 'durationchange'); // Reset timer\n\n            clearInterval(player.timers.buffering); // Setup buffering\n\n            player.timers.buffering = setInterval(() => {\n              // Get loaded % from YouTube\n              player.media.buffered = instance.getVideoLoadedFraction(); // Trigger progress only when we actually buffer something\n\n              if (player.media.lastBuffered === null || player.media.lastBuffered < player.media.buffered) {\n                triggerEvent.call(player, player.media, 'progress');\n              } // Set last buffer point\n\n\n              player.media.lastBuffered = player.media.buffered; // Bail if we're at 100%\n\n              if (player.media.buffered === 1) {\n                clearInterval(player.timers.buffering); // Trigger event\n\n                triggerEvent.call(player, player.media, 'canplaythrough');\n              }\n            }, 200); // Rebuild UI\n\n            if (config.customControls) {\n              setTimeout(() => ui.build.call(player), 50);\n            }\n          },\n\n          onStateChange(event) {\n            // Get the instance\n            const instance = event.target; // Reset timer\n\n            clearInterval(player.timers.playing);\n            const seeked = player.media.seeking && [1, 2].includes(event.data);\n\n            if (seeked) {\n              // Unset seeking and fire seeked event\n              player.media.seeking = false;\n              triggerEvent.call(player, player.media, 'seeked');\n            } // Handle events\n            // -1   Unstarted\n            // 0    Ended\n            // 1    Playing\n            // 2    Paused\n            // 3    Buffering\n            // 5    Video cued\n\n\n            switch (event.data) {\n              case -1:\n                // Update scrubber\n                triggerEvent.call(player, player.media, 'timeupdate'); // Get loaded % from YouTube\n\n                player.media.buffered = instance.getVideoLoadedFraction();\n                triggerEvent.call(player, player.media, 'progress');\n                break;\n\n              case 0:\n                assurePlaybackState.call(player, false); // YouTube doesn't support loop for a single video, so mimick it.\n\n                if (player.media.loop) {\n                  // YouTube needs a call to `stopVideo` before playing again\n                  instance.stopVideo();\n                  instance.playVideo();\n                } else {\n                  triggerEvent.call(player, player.media, 'ended');\n                }\n\n                break;\n\n              case 1:\n                // Restore paused state (YouTube starts playing on seek if the video hasn't been played yet)\n                if (config.customControls && !player.config.autoplay && player.media.paused && !player.embed.hasPlayed) {\n                  player.media.pause();\n                } else {\n                  assurePlaybackState.call(player, true);\n                  triggerEvent.call(player, player.media, 'playing'); // Poll to get playback progress\n\n                  player.timers.playing = setInterval(() => {\n                    triggerEvent.call(player, player.media, 'timeupdate');\n                  }, 50); // Check duration again due to YouTube bug\n                  // https://github.com/sampotts/plyr/issues/374\n                  // https://code.google.com/p/gdata-issues/issues/detail?id=8690\n\n                  if (player.media.duration !== instance.getDuration()) {\n                    player.media.duration = instance.getDuration();\n                    triggerEvent.call(player, player.media, 'durationchange');\n                  }\n                }\n\n                break;\n\n              case 2:\n                // Restore audio (YouTube starts playing on seek if the video hasn't been played yet)\n                if (!player.muted) {\n                  player.embed.unMute();\n                }\n\n                assurePlaybackState.call(player, false);\n                break;\n\n              case 3:\n                // Trigger waiting event to add loading classes to container as the video buffers.\n                triggerEvent.call(player, player.media, 'waiting');\n                break;\n            }\n\n            triggerEvent.call(player, player.elements.container, 'statechange', false, {\n              code: event.data\n            });\n          }\n\n        }\n      });\n    }\n\n  };\n\n  // ==========================================================================\n  const media = {\n    // Setup media\n    setup() {\n      // If there's no media, bail\n      if (!this.media) {\n        this.debug.warn('No media element found!');\n        return;\n      } // Add type class\n\n\n      toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true); // Add provider class\n\n      toggleClass(this.elements.container, this.config.classNames.provider.replace('{0}', this.provider), true); // Add video class for embeds\n      // This will require changes if audio embeds are added\n\n      if (this.isEmbed) {\n        toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true);\n      } // Inject the player wrapper\n\n\n      if (this.isVideo) {\n        // Create the wrapper div\n        this.elements.wrapper = createElement('div', {\n          class: this.config.classNames.video\n        }); // Wrap the video in a container\n\n        wrap(this.media, this.elements.wrapper); // Poster image container\n\n        this.elements.poster = createElement('div', {\n          class: this.config.classNames.poster\n        });\n        this.elements.wrapper.appendChild(this.elements.poster);\n      }\n\n      if (this.isHTML5) {\n        html5.setup.call(this);\n      } else if (this.isYouTube) {\n        youtube.setup.call(this);\n      } else if (this.isVimeo) {\n        vimeo.setup.call(this);\n      }\n    }\n\n  };\n\n  const destroy = instance => {\n    // Destroy our adsManager\n    if (instance.manager) {\n      instance.manager.destroy();\n    } // Destroy our adsManager\n\n\n    if (instance.elements.displayContainer) {\n      instance.elements.displayContainer.destroy();\n    }\n\n    instance.elements.container.remove();\n  };\n\n  class Ads {\n    /**\n     * Ads constructor.\n     * @param {Object} player\n     * @return {Ads}\n     */\n    constructor(player) {\n      _defineProperty$1(this, \"load\", () => {\n        if (!this.enabled) {\n          return;\n        } // Check if the Google IMA3 SDK is loaded or load it ourselves\n\n\n        if (!is.object(window.google) || !is.object(window.google.ima)) {\n          loadScript(this.player.config.urls.googleIMA.sdk).then(() => {\n            this.ready();\n          }).catch(() => {\n            // Script failed to load or is blocked\n            this.trigger('error', new Error('Google IMA SDK failed to load'));\n          });\n        } else {\n          this.ready();\n        }\n      });\n\n      _defineProperty$1(this, \"ready\", () => {\n        // Double check we're enabled\n        if (!this.enabled) {\n          destroy(this);\n        } // Start ticking our safety timer. If the whole advertisement\n        // thing doesn't resolve within our set time; we bail\n\n\n        this.startSafetyTimer(12000, 'ready()'); // Clear the safety timer\n\n        this.managerPromise.then(() => {\n          this.clearSafetyTimer('onAdsManagerLoaded()');\n        }); // Set listeners on the Plyr instance\n\n        this.listeners(); // Setup the IMA SDK\n\n        this.setupIMA();\n      });\n\n      _defineProperty$1(this, \"setupIMA\", () => {\n        // Create the container for our advertisements\n        this.elements.container = createElement('div', {\n          class: this.player.config.classNames.ads\n        });\n        this.player.elements.container.appendChild(this.elements.container); // So we can run VPAID2\n\n        google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED); // Set language\n\n        google.ima.settings.setLocale(this.player.config.ads.language); // Set playback for iOS10+\n\n        google.ima.settings.setDisableCustomPlaybackForIOS10Plus(this.player.config.playsinline); // We assume the adContainer is the video container of the plyr element that will house the ads\n\n        this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container, this.player.media); // Create ads loader\n\n        this.loader = new google.ima.AdsLoader(this.elements.displayContainer); // Listen and respond to ads loaded and error events\n\n        this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, event => this.onAdsManagerLoaded(event), false);\n        this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error), false); // Request video ads to be pre-loaded\n\n        this.requestAds();\n      });\n\n      _defineProperty$1(this, \"requestAds\", () => {\n        const {\n          container\n        } = this.player.elements;\n\n        try {\n          // Request video ads\n          const request = new google.ima.AdsRequest();\n          request.adTagUrl = this.tagUrl; // Specify the linear and nonlinear slot sizes. This helps the SDK\n          // to select the correct creative if multiple are returned\n\n          request.linearAdSlotWidth = container.offsetWidth;\n          request.linearAdSlotHeight = container.offsetHeight;\n          request.nonLinearAdSlotWidth = container.offsetWidth;\n          request.nonLinearAdSlotHeight = container.offsetHeight; // We only overlay ads as we only support video.\n\n          request.forceNonLinearFullSlot = false; // Mute based on current state\n\n          request.setAdWillPlayMuted(!this.player.muted);\n          this.loader.requestAds(request);\n        } catch (error) {\n          this.onAdError(error);\n        }\n      });\n\n      _defineProperty$1(this, \"pollCountdown\", (start = false) => {\n        if (!start) {\n          clearInterval(this.countdownTimer);\n          this.elements.container.removeAttribute('data-badge-text');\n          return;\n        }\n\n        const update = () => {\n          const time = formatTime(Math.max(this.manager.getRemainingTime(), 0));\n          const label = `${i18n.get('advertisement', this.player.config)} - ${time}`;\n          this.elements.container.setAttribute('data-badge-text', label);\n        };\n\n        this.countdownTimer = setInterval(update, 100);\n      });\n\n      _defineProperty$1(this, \"onAdsManagerLoaded\", event => {\n        // Load could occur after a source change (race condition)\n        if (!this.enabled) {\n          return;\n        } // Get the ads manager\n\n\n        const settings = new google.ima.AdsRenderingSettings(); // Tell the SDK to save and restore content video state on our behalf\n\n        settings.restoreCustomPlaybackStateOnAdBreakComplete = true;\n        settings.enablePreloading = true; // The SDK is polling currentTime on the contentPlayback. And needs a duration\n        // so it can determine when to start the mid- and post-roll\n\n        this.manager = event.getAdsManager(this.player, settings); // Get the cue points for any mid-rolls by filtering out the pre- and post-roll\n\n        this.cuePoints = this.manager.getCuePoints(); // Add listeners to the required events\n        // Advertisement error events\n\n        this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error)); // Advertisement regular events\n\n        Object.keys(google.ima.AdEvent.Type).forEach(type => {\n          this.manager.addEventListener(google.ima.AdEvent.Type[type], e => this.onAdEvent(e));\n        }); // Resolve our adsManager\n\n        this.trigger('loaded');\n      });\n\n      _defineProperty$1(this, \"addCuePoints\", () => {\n        // Add advertisement cue's within the time line if available\n        if (!is.empty(this.cuePoints)) {\n          this.cuePoints.forEach(cuePoint => {\n            if (cuePoint !== 0 && cuePoint !== -1 && cuePoint < this.player.duration) {\n              const seekElement = this.player.elements.progress;\n\n              if (is.element(seekElement)) {\n                const cuePercentage = 100 / this.player.duration * cuePoint;\n                const cue = createElement('span', {\n                  class: this.player.config.classNames.cues\n                });\n                cue.style.left = `${cuePercentage.toString()}%`;\n                seekElement.appendChild(cue);\n              }\n            }\n          });\n        }\n      });\n\n      _defineProperty$1(this, \"onAdEvent\", event => {\n        const {\n          container\n        } = this.player.elements; // Retrieve the ad from the event. Some events (e.g. ALL_ADS_COMPLETED)\n        // don't have ad object associated\n\n        const ad = event.getAd();\n        const adData = event.getAdData(); // Proxy event\n\n        const dispatchEvent = type => {\n          triggerEvent.call(this.player, this.player.media, `ads${type.replace(/_/g, '').toLowerCase()}`);\n        }; // Bubble the event\n\n\n        dispatchEvent(event.type);\n\n        switch (event.type) {\n          case google.ima.AdEvent.Type.LOADED:\n            // This is the first event sent for an ad - it is possible to determine whether the\n            // ad is a video ad or an overlay\n            this.trigger('loaded'); // Start countdown\n\n            this.pollCountdown(true);\n\n            if (!ad.isLinear()) {\n              // Position AdDisplayContainer correctly for overlay\n              ad.width = container.offsetWidth;\n              ad.height = container.offsetHeight;\n            } // console.info('Ad type: ' + event.getAd().getAdPodInfo().getPodIndex());\n            // console.info('Ad time: ' + event.getAd().getAdPodInfo().getTimeOffset());\n\n\n            break;\n\n          case google.ima.AdEvent.Type.STARTED:\n            // Set volume to match player\n            this.manager.setVolume(this.player.volume);\n            break;\n\n          case google.ima.AdEvent.Type.ALL_ADS_COMPLETED:\n            // All ads for the current videos are done. We can now request new advertisements\n            // in case the video is re-played\n            // TODO: Example for what happens when a next video in a playlist would be loaded.\n            // So here we load a new video when all ads are done.\n            // Then we load new ads within a new adsManager. When the video\n            // Is started - after - the ads are loaded, then we get ads.\n            // You can also easily test cancelling and reloading by running\n            // player.ads.cancel() and player.ads.play from the console I guess.\n            // this.player.source = {\n            //     type: 'video',\n            //     title: 'View From A Blue Moon',\n            //     sources: [{\n            //         src:\n            // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.mp4', type:\n            // 'video/mp4', }], poster:\n            // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg', tracks:\n            // [ { kind: 'captions', label: 'English', srclang: 'en', src:\n            // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt',\n            // default: true, }, { kind: 'captions', label: 'French', srclang: 'fr', src:\n            // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt', }, ],\n            // };\n            // TODO: So there is still this thing where a video should only be allowed to start\n            // playing when the IMA SDK is ready or has failed\n            if (this.player.ended) {\n              this.loadAds();\n            } else {\n              // The SDK won't allow new ads to be called without receiving a contentComplete()\n              this.loader.contentComplete();\n            }\n\n            break;\n\n          case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:\n            // This event indicates the ad has started - the video player can adjust the UI,\n            // for example display a pause button and remaining time. Fired when content should\n            // be paused. This usually happens right before an ad is about to cover the content\n            this.pauseContent();\n            break;\n\n          case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED:\n            // This event indicates the ad has finished - the video player can perform\n            // appropriate UI actions, such as removing the timer for remaining time detection.\n            // Fired when content should be resumed. This usually happens when an ad finishes\n            // or collapses\n            this.pollCountdown();\n            this.resumeContent();\n            break;\n\n          case google.ima.AdEvent.Type.LOG:\n            if (adData.adError) {\n              this.player.debug.warn(`Non-fatal ad error: ${adData.adError.getMessage()}`);\n            }\n\n            break;\n        }\n      });\n\n      _defineProperty$1(this, \"onAdError\", event => {\n        this.cancel();\n        this.player.debug.warn('Ads error', event);\n      });\n\n      _defineProperty$1(this, \"listeners\", () => {\n        const {\n          container\n        } = this.player.elements;\n        let time;\n        this.player.on('canplay', () => {\n          this.addCuePoints();\n        });\n        this.player.on('ended', () => {\n          this.loader.contentComplete();\n        });\n        this.player.on('timeupdate', () => {\n          time = this.player.currentTime;\n        });\n        this.player.on('seeked', () => {\n          const seekedTime = this.player.currentTime;\n\n          if (is.empty(this.cuePoints)) {\n            return;\n          }\n\n          this.cuePoints.forEach((cuePoint, index) => {\n            if (time < cuePoint && cuePoint < seekedTime) {\n              this.manager.discardAdBreak();\n              this.cuePoints.splice(index, 1);\n            }\n          });\n        }); // Listen to the resizing of the window. And resize ad accordingly\n        // TODO: eventually implement ResizeObserver\n\n        window.addEventListener('resize', () => {\n          if (this.manager) {\n            this.manager.resize(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);\n          }\n        });\n      });\n\n      _defineProperty$1(this, \"play\", () => {\n        const {\n          container\n        } = this.player.elements;\n\n        if (!this.managerPromise) {\n          this.resumeContent();\n        } // Play the requested advertisement whenever the adsManager is ready\n\n\n        this.managerPromise.then(() => {\n          // Set volume to match player\n          this.manager.setVolume(this.player.volume); // Initialize the container. Must be done via a user action on mobile devices\n\n          this.elements.displayContainer.initialize();\n\n          try {\n            if (!this.initialized) {\n              // Initialize the ads manager. Ad rules playlist will start at this time\n              this.manager.init(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will\n              // start at this time; the call will be ignored for ad rules\n\n              this.manager.start();\n            }\n\n            this.initialized = true;\n          } catch (adError) {\n            // An error may be thrown if there was a problem with the\n            // VAST response\n            this.onAdError(adError);\n          }\n        }).catch(() => {});\n      });\n\n      _defineProperty$1(this, \"resumeContent\", () => {\n        // Hide the advertisement container\n        this.elements.container.style.zIndex = ''; // Ad is stopped\n\n        this.playing = false; // Play video\n\n        silencePromise(this.player.media.play());\n      });\n\n      _defineProperty$1(this, \"pauseContent\", () => {\n        // Show the advertisement container\n        this.elements.container.style.zIndex = 3; // Ad is playing\n\n        this.playing = true; // Pause our video.\n\n        this.player.media.pause();\n      });\n\n      _defineProperty$1(this, \"cancel\", () => {\n        // Pause our video\n        if (this.initialized) {\n          this.resumeContent();\n        } // Tell our instance that we're done for now\n\n\n        this.trigger('error'); // Re-create our adsManager\n\n        this.loadAds();\n      });\n\n      _defineProperty$1(this, \"loadAds\", () => {\n        // Tell our adsManager to go bye bye\n        this.managerPromise.then(() => {\n          // Destroy our adsManager\n          if (this.manager) {\n            this.manager.destroy();\n          } // Re-set our adsManager promises\n\n\n          this.managerPromise = new Promise(resolve => {\n            this.on('loaded', resolve);\n            this.player.debug.log(this.manager);\n          }); // Now that the manager has been destroyed set it to also be un-initialized\n\n          this.initialized = false; // Now request some new advertisements\n\n          this.requestAds();\n        }).catch(() => {});\n      });\n\n      _defineProperty$1(this, \"trigger\", (event, ...args) => {\n        const handlers = this.events[event];\n\n        if (is.array(handlers)) {\n          handlers.forEach(handler => {\n            if (is.function(handler)) {\n              handler.apply(this, args);\n            }\n          });\n        }\n      });\n\n      _defineProperty$1(this, \"on\", (event, callback) => {\n        if (!is.array(this.events[event])) {\n          this.events[event] = [];\n        }\n\n        this.events[event].push(callback);\n        return this;\n      });\n\n      _defineProperty$1(this, \"startSafetyTimer\", (time, from) => {\n        this.player.debug.log(`Safety timer invoked from: ${from}`);\n        this.safetyTimer = setTimeout(() => {\n          this.cancel();\n          this.clearSafetyTimer('startSafetyTimer()');\n        }, time);\n      });\n\n      _defineProperty$1(this, \"clearSafetyTimer\", from => {\n        if (!is.nullOrUndefined(this.safetyTimer)) {\n          this.player.debug.log(`Safety timer cleared from: ${from}`);\n          clearTimeout(this.safetyTimer);\n          this.safetyTimer = null;\n        }\n      });\n\n      this.player = player;\n      this.config = player.config.ads;\n      this.playing = false;\n      this.initialized = false;\n      this.elements = {\n        container: null,\n        displayContainer: null\n      };\n      this.manager = null;\n      this.loader = null;\n      this.cuePoints = null;\n      this.events = {};\n      this.safetyTimer = null;\n      this.countdownTimer = null; // Setup a promise to resolve when the IMA manager is ready\n\n      this.managerPromise = new Promise((resolve, reject) => {\n        // The ad is loaded and ready\n        this.on('loaded', resolve); // Ads failed\n\n        this.on('error', reject);\n      });\n      this.load();\n    }\n\n    get enabled() {\n      const {\n        config\n      } = this;\n      return this.player.isHTML5 && this.player.isVideo && config.enabled && (!is.empty(config.publisherId) || is.url(config.tagUrl));\n    }\n    /**\n     * Load the IMA SDK\n     */\n\n\n    // Build the tag URL\n    get tagUrl() {\n      const {\n        config\n      } = this;\n\n      if (is.url(config.tagUrl)) {\n        return config.tagUrl;\n      }\n\n      const params = {\n        AV_PUBLISHERID: '58c25bb0073ef448b1087ad6',\n        AV_CHANNELID: '5a0458dc28a06145e4519d21',\n        AV_URL: window.location.hostname,\n        cb: Date.now(),\n        AV_WIDTH: 640,\n        AV_HEIGHT: 480,\n        AV_CDIM2: config.publisherId\n      };\n      const base = 'https://go.aniview.com/api/adserver6/vast/';\n      return `${base}?${buildUrlParams(params)}`;\n    }\n    /**\n     * In order for the SDK to display ads for our video, we need to tell it where to put them,\n     * so here we define our ad container. This div is set up to render on top of the video player.\n     * Using the code below, we tell the SDK to render ads within that div. We also provide a\n     * handle to the content video player - the SDK will poll the current time of our player to\n     * properly place mid-rolls. After we create the ad display container, we initialize it. On\n     * mobile devices, this initialization is done as the result of a user action.\n     */\n\n\n  }\n\n  const parseVtt = vttDataString => {\n    const processedList = [];\n    const frames = vttDataString.split(/\\r\\n\\r\\n|\\n\\n|\\r\\r/);\n    frames.forEach(frame => {\n      const result = {};\n      const lines = frame.split(/\\r\\n|\\n|\\r/);\n      lines.forEach(line => {\n        if (!is.number(result.startTime)) {\n          // The line with start and end times on it is the first line of interest\n          const matchTimes = line.match(/([0-9]{2})?:?([0-9]{2}):([0-9]{2}).([0-9]{2,3})( ?--> ?)([0-9]{2})?:?([0-9]{2}):([0-9]{2}).([0-9]{2,3})/); // Note that this currently ignores caption formatting directives that are optionally on the end of this line - fine for non-captions VTT\n\n          if (matchTimes) {\n            result.startTime = Number(matchTimes[1] || 0) * 60 * 60 + Number(matchTimes[2]) * 60 + Number(matchTimes[3]) + Number(`0.${matchTimes[4]}`);\n            result.endTime = Number(matchTimes[6] || 0) * 60 * 60 + Number(matchTimes[7]) * 60 + Number(matchTimes[8]) + Number(`0.${matchTimes[9]}`);\n          }\n        } else if (!is.empty(line.trim()) && is.empty(result.text)) {\n          // If we already have the startTime, then we're definitely up to the text line(s)\n          const lineSplit = line.trim().split('#xywh=');\n          [result.text] = lineSplit; // If there's content in lineSplit[1], then we have sprites. If not, then it's just one frame per image\n\n          if (lineSplit[1]) {\n            [result.x, result.y, result.w, result.h] = lineSplit[1].split(',');\n          }\n        }\n      });\n\n      if (result.text) {\n        processedList.push(result);\n      }\n    });\n    return processedList;\n  };\n  /**\n   * Preview thumbnails for seek hover and scrubbing\n   * Seeking: Hover over the seek bar (desktop only): shows a small preview container above the seek bar\n   * Scrubbing: Click and drag the seek bar (desktop and mobile): shows the preview image over the entire video, as if the video is scrubbing at very high speed\n   *\n   * Notes:\n   * - Thumbs are set via JS settings on Plyr init, not HTML5 'track' property. Using the track property would be a bit gross, because it doesn't support custom 'kinds'. kind=metadata might be used for something else, and we want to allow multiple thumbnails tracks. Tracks must have a unique combination of 'kind' and 'label'. We would have to do something like kind=metadata,label=thumbnails1 / kind=metadata,label=thumbnails2. Square peg, round hole\n   * - VTT info: the image URL is relative to the VTT, not the current document. But if the url starts with a slash, it will naturally be relative to the current domain. https://support.jwplayer.com/articles/how-to-add-preview-thumbnails\n   * - This implementation uses multiple separate img elements. Other implementations use background-image on one element. This would be nice and simple, but Firefox and Safari have flickering issues with replacing backgrounds of larger images. It seems that YouTube perhaps only avoids this because they don't have the option for high-res previews (even the fullscreen ones, when mousedown/seeking). Images appear over the top of each other, and previous ones are discarded once the new ones have been rendered\n   */\n\n\n  const fitRatio = (ratio, outer) => {\n    const targetRatio = outer.width / outer.height;\n    const result = {};\n\n    if (ratio > targetRatio) {\n      result.width = outer.width;\n      result.height = 1 / ratio * outer.width;\n    } else {\n      result.height = outer.height;\n      result.width = ratio * outer.height;\n    }\n\n    return result;\n  };\n\n  class PreviewThumbnails {\n    /**\n     * PreviewThumbnails constructor.\n     * @param {Plyr} player\n     * @return {PreviewThumbnails}\n     */\n    constructor(player) {\n      _defineProperty$1(this, \"load\", () => {\n        // Toggle the regular seek tooltip\n        if (this.player.elements.display.seekTooltip) {\n          this.player.elements.display.seekTooltip.hidden = this.enabled;\n        }\n\n        if (!this.enabled) {\n          return;\n        }\n\n        this.getThumbnails().then(() => {\n          if (!this.enabled) {\n            return;\n          } // Render DOM elements\n\n\n          this.render(); // Check to see if thumb container size was specified manually in CSS\n\n          this.determineContainerAutoSizing();\n          this.loaded = true;\n        });\n      });\n\n      _defineProperty$1(this, \"getThumbnails\", () => {\n        return new Promise(resolve => {\n          const {\n            src\n          } = this.player.config.previewThumbnails;\n\n          if (is.empty(src)) {\n            throw new Error('Missing previewThumbnails.src config attribute');\n          } // Resolve promise\n\n\n          const sortAndResolve = () => {\n            // Sort smallest to biggest (e.g., [120p, 480p, 1080p])\n            this.thumbnails.sort((x, y) => x.height - y.height);\n            this.player.debug.log('Preview thumbnails', this.thumbnails);\n            resolve();\n          }; // Via callback()\n\n\n          if (is.function(src)) {\n            src(thumbnails => {\n              this.thumbnails = thumbnails;\n              sortAndResolve();\n            });\n          } // VTT urls\n          else {\n            // If string, convert into single-element list\n            const urls = is.string(src) ? [src] : src; // Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails\n\n            const promises = urls.map(u => this.getThumbnail(u)); // Resolve\n\n            Promise.all(promises).then(sortAndResolve);\n          }\n        });\n      });\n\n      _defineProperty$1(this, \"getThumbnail\", url => {\n        return new Promise(resolve => {\n          fetch(url).then(response => {\n            const thumbnail = {\n              frames: parseVtt(response),\n              height: null,\n              urlPrefix: ''\n            }; // If the URLs don't start with '/', then we need to set their relative path to be the location of the VTT file\n            // If the URLs do start with '/', then they obviously don't need a prefix, so it will remain blank\n            // If the thumbnail URLs start with with none of '/', 'http://' or 'https://', then we need to set their relative path to be the location of the VTT file\n\n            if (!thumbnail.frames[0].text.startsWith('/') && !thumbnail.frames[0].text.startsWith('http://') && !thumbnail.frames[0].text.startsWith('https://')) {\n              thumbnail.urlPrefix = url.substring(0, url.lastIndexOf('/') + 1);\n            } // Download the first frame, so that we can determine/set the height of this thumbnailsDef\n\n\n            const tempImage = new Image();\n\n            tempImage.onload = () => {\n              thumbnail.height = tempImage.naturalHeight;\n              thumbnail.width = tempImage.naturalWidth;\n              this.thumbnails.push(thumbnail);\n              resolve();\n            };\n\n            tempImage.src = thumbnail.urlPrefix + thumbnail.frames[0].text;\n          });\n        });\n      });\n\n      _defineProperty$1(this, \"startMove\", event => {\n        if (!this.loaded) {\n          return;\n        }\n\n        if (!is.event(event) || !['touchmove', 'mousemove'].includes(event.type)) {\n          return;\n        } // Wait until media has a duration\n\n\n        if (!this.player.media.duration) {\n          return;\n        }\n\n        if (event.type === 'touchmove') {\n          // Calculate seek hover position as approx video seconds\n          this.seekTime = this.player.media.duration * (this.player.elements.inputs.seek.value / 100);\n        } else {\n          // Calculate seek hover position as approx video seconds\n          const clientRect = this.player.elements.progress.getBoundingClientRect();\n          const percentage = 100 / clientRect.width * (event.pageX - clientRect.left);\n          this.seekTime = this.player.media.duration * (percentage / 100);\n\n          if (this.seekTime < 0) {\n            // The mousemove fires for 10+px out to the left\n            this.seekTime = 0;\n          }\n\n          if (this.seekTime > this.player.media.duration - 1) {\n            // Took 1 second off the duration for safety, because different players can disagree on the real duration of a video\n            this.seekTime = this.player.media.duration - 1;\n          }\n\n          this.mousePosX = event.pageX; // Set time text inside image container\n\n          this.elements.thumb.time.innerText = formatTime(this.seekTime);\n        } // Download and show image\n\n\n        this.showImageAtCurrentTime();\n      });\n\n      _defineProperty$1(this, \"endMove\", () => {\n        this.toggleThumbContainer(false, true);\n      });\n\n      _defineProperty$1(this, \"startScrubbing\", event => {\n        // Only act on left mouse button (0), or touch device (event.button does not exist or is false)\n        if (is.nullOrUndefined(event.button) || event.button === false || event.button === 0) {\n          this.mouseDown = true; // Wait until media has a duration\n\n          if (this.player.media.duration) {\n            this.toggleScrubbingContainer(true);\n            this.toggleThumbContainer(false, true); // Download and show image\n\n            this.showImageAtCurrentTime();\n          }\n        }\n      });\n\n      _defineProperty$1(this, \"endScrubbing\", () => {\n        this.mouseDown = false; // Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview\n\n        if (Math.ceil(this.lastTime) === Math.ceil(this.player.media.currentTime)) {\n          // The video was already seeked/loaded at the chosen time - hide immediately\n          this.toggleScrubbingContainer(false);\n        } else {\n          // The video hasn't seeked yet. Wait for that\n          once.call(this.player, this.player.media, 'timeupdate', () => {\n            // Re-check mousedown - we might have already started scrubbing again\n            if (!this.mouseDown) {\n              this.toggleScrubbingContainer(false);\n            }\n          });\n        }\n      });\n\n      _defineProperty$1(this, \"listeners\", () => {\n        // Hide thumbnail preview - on mouse click, mouse leave (in listeners.js for now), and video play/seek. All four are required, e.g., for buffering\n        this.player.on('play', () => {\n          this.toggleThumbContainer(false, true);\n        });\n        this.player.on('seeked', () => {\n          this.toggleThumbContainer(false);\n        });\n        this.player.on('timeupdate', () => {\n          this.lastTime = this.player.media.currentTime;\n        });\n      });\n\n      _defineProperty$1(this, \"render\", () => {\n        // Create HTML element: plyr__preview-thumbnail-container\n        this.elements.thumb.container = createElement('div', {\n          class: this.player.config.classNames.previewThumbnails.thumbContainer\n        }); // Wrapper for the image for styling\n\n        this.elements.thumb.imageContainer = createElement('div', {\n          class: this.player.config.classNames.previewThumbnails.imageContainer\n        });\n        this.elements.thumb.container.appendChild(this.elements.thumb.imageContainer); // Create HTML element, parent+span: time text (e.g., 01:32:00)\n\n        const timeContainer = createElement('div', {\n          class: this.player.config.classNames.previewThumbnails.timeContainer\n        });\n        this.elements.thumb.time = createElement('span', {}, '00:00');\n        timeContainer.appendChild(this.elements.thumb.time);\n        this.elements.thumb.container.appendChild(timeContainer); // Inject the whole thumb\n\n        if (is.element(this.player.elements.progress)) {\n          this.player.elements.progress.appendChild(this.elements.thumb.container);\n        } // Create HTML element: plyr__preview-scrubbing-container\n\n\n        this.elements.scrubbing.container = createElement('div', {\n          class: this.player.config.classNames.previewThumbnails.scrubbingContainer\n        });\n        this.player.elements.wrapper.appendChild(this.elements.scrubbing.container);\n      });\n\n      _defineProperty$1(this, \"destroy\", () => {\n        if (this.elements.thumb.container) {\n          this.elements.thumb.container.remove();\n        }\n\n        if (this.elements.scrubbing.container) {\n          this.elements.scrubbing.container.remove();\n        }\n      });\n\n      _defineProperty$1(this, \"showImageAtCurrentTime\", () => {\n        if (this.mouseDown) {\n          this.setScrubbingContainerSize();\n        } else {\n          this.setThumbContainerSizeAndPos();\n        } // Find the desired thumbnail index\n        // TODO: Handle a video longer than the thumbs where thumbNum is null\n\n\n        const thumbNum = this.thumbnails[0].frames.findIndex(frame => this.seekTime >= frame.startTime && this.seekTime <= frame.endTime);\n        const hasThumb = thumbNum >= 0;\n        let qualityIndex = 0; // Show the thumb container if we're not scrubbing\n\n        if (!this.mouseDown) {\n          this.toggleThumbContainer(hasThumb);\n        } // No matching thumb found\n\n\n        if (!hasThumb) {\n          return;\n        } // Check to see if we've already downloaded higher quality versions of this image\n\n\n        this.thumbnails.forEach((thumbnail, index) => {\n          if (this.loadedImages.includes(thumbnail.frames[thumbNum].text)) {\n            qualityIndex = index;\n          }\n        }); // Only proceed if either thumbnum or thumbfilename has changed\n\n        if (thumbNum !== this.showingThumb) {\n          this.showingThumb = thumbNum;\n          this.loadImage(qualityIndex);\n        }\n      });\n\n      _defineProperty$1(this, \"loadImage\", (qualityIndex = 0) => {\n        const thumbNum = this.showingThumb;\n        const thumbnail = this.thumbnails[qualityIndex];\n        const {\n          urlPrefix\n        } = thumbnail;\n        const frame = thumbnail.frames[thumbNum];\n        const thumbFilename = thumbnail.frames[thumbNum].text;\n        const thumbUrl = urlPrefix + thumbFilename;\n\n        if (!this.currentImageElement || this.currentImageElement.dataset.filename !== thumbFilename) {\n          // If we're already loading a previous image, remove its onload handler - we don't want it to load after this one\n          // Only do this if not using sprites. Without sprites we really want to show as many images as possible, as a best-effort\n          if (this.loadingImage && this.usingSprites) {\n            this.loadingImage.onload = null;\n          } // We're building and adding a new image. In other implementations of similar functionality (YouTube), background image\n          // is instead used. But this causes issues with larger images in Firefox and Safari - switching between background\n          // images causes a flicker. Putting a new image over the top does not\n\n\n          const previewImage = new Image();\n          previewImage.src = thumbUrl;\n          previewImage.dataset.index = thumbNum;\n          previewImage.dataset.filename = thumbFilename;\n          this.showingThumbFilename = thumbFilename;\n          this.player.debug.log(`Loading image: ${thumbUrl}`); // For some reason, passing the named function directly causes it to execute immediately. So I've wrapped it in an anonymous function...\n\n          previewImage.onload = () => this.showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, true);\n\n          this.loadingImage = previewImage;\n          this.removeOldImages(previewImage);\n        } else {\n          // Update the existing image\n          this.showImage(this.currentImageElement, frame, qualityIndex, thumbNum, thumbFilename, false);\n          this.currentImageElement.dataset.index = thumbNum;\n          this.removeOldImages(this.currentImageElement);\n        }\n      });\n\n      _defineProperty$1(this, \"showImage\", (previewImage, frame, qualityIndex, thumbNum, thumbFilename, newImage = true) => {\n        this.player.debug.log(`Showing thumb: ${thumbFilename}. num: ${thumbNum}. qual: ${qualityIndex}. newimg: ${newImage}`);\n        this.setImageSizeAndOffset(previewImage, frame);\n\n        if (newImage) {\n          this.currentImageContainer.appendChild(previewImage);\n          this.currentImageElement = previewImage;\n\n          if (!this.loadedImages.includes(thumbFilename)) {\n            this.loadedImages.push(thumbFilename);\n          }\n        } // Preload images before and after the current one\n        // Show higher quality of the same frame\n        // Each step here has a short time delay, and only continues if still hovering/seeking the same spot. This is to protect slow connections from overloading\n\n\n        this.preloadNearby(thumbNum, true).then(this.preloadNearby(thumbNum, false)).then(this.getHigherQuality(qualityIndex, previewImage, frame, thumbFilename));\n      });\n\n      _defineProperty$1(this, \"removeOldImages\", currentImage => {\n        // Get a list of all images, convert it from a DOM list to an array\n        Array.from(this.currentImageContainer.children).forEach(image => {\n          if (image.tagName.toLowerCase() !== 'img') {\n            return;\n          }\n\n          const removeDelay = this.usingSprites ? 500 : 1000;\n\n          if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) {\n            // Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients\n            // First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function\n            // eslint-disable-next-line no-param-reassign\n            image.dataset.deleting = true; // This has to be set before the timeout - to prevent issues switching between hover and scrub\n\n            const {\n              currentImageContainer\n            } = this;\n            setTimeout(() => {\n              currentImageContainer.removeChild(image);\n              this.player.debug.log(`Removing thumb: ${image.dataset.filename}`);\n            }, removeDelay);\n          }\n        });\n      });\n\n      _defineProperty$1(this, \"preloadNearby\", (thumbNum, forward = true) => {\n        return new Promise(resolve => {\n          setTimeout(() => {\n            const oldThumbFilename = this.thumbnails[0].frames[thumbNum].text;\n\n            if (this.showingThumbFilename === oldThumbFilename) {\n              // Find the nearest thumbs with different filenames. Sometimes it'll be the next index, but in the case of sprites, it might be 100+ away\n              let thumbnailsClone;\n\n              if (forward) {\n                thumbnailsClone = this.thumbnails[0].frames.slice(thumbNum);\n              } else {\n                thumbnailsClone = this.thumbnails[0].frames.slice(0, thumbNum).reverse();\n              }\n\n              let foundOne = false;\n              thumbnailsClone.forEach(frame => {\n                const newThumbFilename = frame.text;\n\n                if (newThumbFilename !== oldThumbFilename) {\n                  // Found one with a different filename. Make sure it hasn't already been loaded on this page visit\n                  if (!this.loadedImages.includes(newThumbFilename)) {\n                    foundOne = true;\n                    this.player.debug.log(`Preloading thumb filename: ${newThumbFilename}`);\n                    const {\n                      urlPrefix\n                    } = this.thumbnails[0];\n                    const thumbURL = urlPrefix + newThumbFilename;\n                    const previewImage = new Image();\n                    previewImage.src = thumbURL;\n\n                    previewImage.onload = () => {\n                      this.player.debug.log(`Preloaded thumb filename: ${newThumbFilename}`);\n                      if (!this.loadedImages.includes(newThumbFilename)) this.loadedImages.push(newThumbFilename); // We don't resolve until the thumb is loaded\n\n                      resolve();\n                    };\n                  }\n                }\n              }); // If there are none to preload then we want to resolve immediately\n\n              if (!foundOne) {\n                resolve();\n              }\n            }\n          }, 300);\n        });\n      });\n\n      _defineProperty$1(this, \"getHigherQuality\", (currentQualityIndex, previewImage, frame, thumbFilename) => {\n        if (currentQualityIndex < this.thumbnails.length - 1) {\n          // Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container\n          let previewImageHeight = previewImage.naturalHeight;\n\n          if (this.usingSprites) {\n            previewImageHeight = frame.h;\n          }\n\n          if (previewImageHeight < this.thumbContainerHeight) {\n            // Recurse back to the loadImage function - show a higher quality one, but only if the viewer is on this frame for a while\n            setTimeout(() => {\n              // Make sure the mouse hasn't already moved on and started hovering at another image\n              if (this.showingThumbFilename === thumbFilename) {\n                this.player.debug.log(`Showing higher quality thumb for: ${thumbFilename}`);\n                this.loadImage(currentQualityIndex + 1);\n              }\n            }, 300);\n          }\n        }\n      });\n\n      _defineProperty$1(this, \"toggleThumbContainer\", (toggle = false, clearShowing = false) => {\n        const className = this.player.config.classNames.previewThumbnails.thumbContainerShown;\n        this.elements.thumb.container.classList.toggle(className, toggle);\n\n        if (!toggle && clearShowing) {\n          this.showingThumb = null;\n          this.showingThumbFilename = null;\n        }\n      });\n\n      _defineProperty$1(this, \"toggleScrubbingContainer\", (toggle = false) => {\n        const className = this.player.config.classNames.previewThumbnails.scrubbingContainerShown;\n        this.elements.scrubbing.container.classList.toggle(className, toggle);\n\n        if (!toggle) {\n          this.showingThumb = null;\n          this.showingThumbFilename = null;\n        }\n      });\n\n      _defineProperty$1(this, \"determineContainerAutoSizing\", () => {\n        if (this.elements.thumb.imageContainer.clientHeight > 20 || this.elements.thumb.imageContainer.clientWidth > 20) {\n          // This will prevent auto sizing in this.setThumbContainerSizeAndPos()\n          this.sizeSpecifiedInCSS = true;\n        }\n      });\n\n      _defineProperty$1(this, \"setThumbContainerSizeAndPos\", () => {\n        if (!this.sizeSpecifiedInCSS) {\n          const thumbWidth = Math.floor(this.thumbContainerHeight * this.thumbAspectRatio);\n          this.elements.thumb.imageContainer.style.height = `${this.thumbContainerHeight}px`;\n          this.elements.thumb.imageContainer.style.width = `${thumbWidth}px`;\n        } else if (this.elements.thumb.imageContainer.clientHeight > 20 && this.elements.thumb.imageContainer.clientWidth < 20) {\n          const thumbWidth = Math.floor(this.elements.thumb.imageContainer.clientHeight * this.thumbAspectRatio);\n          this.elements.thumb.imageContainer.style.width = `${thumbWidth}px`;\n        } else if (this.elements.thumb.imageContainer.clientHeight < 20 && this.elements.thumb.imageContainer.clientWidth > 20) {\n          const thumbHeight = Math.floor(this.elements.thumb.imageContainer.clientWidth / this.thumbAspectRatio);\n          this.elements.thumb.imageContainer.style.height = `${thumbHeight}px`;\n        }\n\n        this.setThumbContainerPos();\n      });\n\n      _defineProperty$1(this, \"setThumbContainerPos\", () => {\n        const seekbarRect = this.player.elements.progress.getBoundingClientRect();\n        const plyrRect = this.player.elements.container.getBoundingClientRect();\n        const {\n          container\n        } = this.elements.thumb; // Find the lowest and highest desired left-position, so we don't slide out the side of the video container\n\n        const minVal = plyrRect.left - seekbarRect.left + 10;\n        const maxVal = plyrRect.right - seekbarRect.left - container.clientWidth - 10; // Set preview container position to: mousepos, minus seekbar.left, minus half of previewContainer.clientWidth\n\n        let previewPos = this.mousePosX - seekbarRect.left - container.clientWidth / 2;\n\n        if (previewPos < minVal) {\n          previewPos = minVal;\n        }\n\n        if (previewPos > maxVal) {\n          previewPos = maxVal;\n        }\n\n        container.style.left = `${previewPos}px`;\n      });\n\n      _defineProperty$1(this, \"setScrubbingContainerSize\", () => {\n        const {\n          width,\n          height\n        } = fitRatio(this.thumbAspectRatio, {\n          width: this.player.media.clientWidth,\n          height: this.player.media.clientHeight\n        });\n        this.elements.scrubbing.container.style.width = `${width}px`;\n        this.elements.scrubbing.container.style.height = `${height}px`;\n      });\n\n      _defineProperty$1(this, \"setImageSizeAndOffset\", (previewImage, frame) => {\n        if (!this.usingSprites) {\n          return;\n        } // Find difference between height and preview container height\n\n\n        const multiplier = this.thumbContainerHeight / frame.h; // eslint-disable-next-line no-param-reassign\n\n        previewImage.style.height = `${previewImage.naturalHeight * multiplier}px`; // eslint-disable-next-line no-param-reassign\n\n        previewImage.style.width = `${previewImage.naturalWidth * multiplier}px`; // eslint-disable-next-line no-param-reassign\n\n        previewImage.style.left = `-${frame.x * multiplier}px`; // eslint-disable-next-line no-param-reassign\n\n        previewImage.style.top = `-${frame.y * multiplier}px`;\n      });\n\n      this.player = player;\n      this.thumbnails = [];\n      this.loaded = false;\n      this.lastMouseMoveTime = Date.now();\n      this.mouseDown = false;\n      this.loadedImages = [];\n      this.elements = {\n        thumb: {},\n        scrubbing: {}\n      };\n      this.load();\n    }\n\n    get enabled() {\n      return this.player.isHTML5 && this.player.isVideo && this.player.config.previewThumbnails.enabled;\n    }\n\n    get currentImageContainer() {\n      if (this.mouseDown) {\n        return this.elements.scrubbing.container;\n      }\n\n      return this.elements.thumb.imageContainer;\n    }\n\n    get usingSprites() {\n      return Object.keys(this.thumbnails[0].frames[0]).includes('w');\n    }\n\n    get thumbAspectRatio() {\n      if (this.usingSprites) {\n        return this.thumbnails[0].frames[0].w / this.thumbnails[0].frames[0].h;\n      }\n\n      return this.thumbnails[0].width / this.thumbnails[0].height;\n    }\n\n    get thumbContainerHeight() {\n      if (this.mouseDown) {\n        const {\n          height\n        } = fitRatio(this.thumbAspectRatio, {\n          width: this.player.media.clientWidth,\n          height: this.player.media.clientHeight\n        });\n        return height;\n      } // If css is used this needs to return the css height for sprites to work (see setImageSizeAndOffset)\n\n\n      if (this.sizeSpecifiedInCSS) {\n        return this.elements.thumb.imageContainer.clientHeight;\n      }\n\n      return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio / 4);\n    }\n\n    get currentImageElement() {\n      if (this.mouseDown) {\n        return this.currentScrubbingImageElement;\n      }\n\n      return this.currentThumbnailImageElement;\n    }\n\n    set currentImageElement(element) {\n      if (this.mouseDown) {\n        this.currentScrubbingImageElement = element;\n      } else {\n        this.currentThumbnailImageElement = element;\n      }\n    }\n\n  }\n\n  // ==========================================================================\n  const source = {\n    // Add elements to HTML5 media (source, tracks, etc)\n    insertElements(type, attributes) {\n      if (is.string(attributes)) {\n        insertElement(type, this.media, {\n          src: attributes\n        });\n      } else if (is.array(attributes)) {\n        attributes.forEach(attribute => {\n          insertElement(type, this.media, attribute);\n        });\n      }\n    },\n\n    // Update source\n    // Sources are not checked for support so be careful\n    change(input) {\n      if (!getDeep(input, 'sources.length')) {\n        this.debug.warn('Invalid source format');\n        return;\n      } // Cancel current network requests\n\n\n      html5.cancelRequests.call(this); // Destroy instance and re-setup\n\n      this.destroy.call(this, () => {\n        // Reset quality options\n        this.options.quality = []; // Remove elements\n\n        removeElement(this.media);\n        this.media = null; // Reset class name\n\n        if (is.element(this.elements.container)) {\n          this.elements.container.removeAttribute('class');\n        } // Set the type and provider\n\n\n        const {\n          sources,\n          type\n        } = input;\n        const [{\n          provider = providers.html5,\n          src\n        }] = sources;\n        const tagName = provider === 'html5' ? type : 'div';\n        const attributes = provider === 'html5' ? {} : {\n          src\n        };\n        Object.assign(this, {\n          provider,\n          type,\n          // Check for support\n          supported: support.check(type, provider, this.config.playsinline),\n          // Create new element\n          media: createElement(tagName, attributes)\n        }); // Inject the new element\n\n        this.elements.container.appendChild(this.media); // Autoplay the new source?\n\n        if (is.boolean(input.autoplay)) {\n          this.config.autoplay = input.autoplay;\n        } // Set attributes for audio and video\n\n\n        if (this.isHTML5) {\n          if (this.config.crossorigin) {\n            this.media.setAttribute('crossorigin', '');\n          }\n\n          if (this.config.autoplay) {\n            this.media.setAttribute('autoplay', '');\n          }\n\n          if (!is.empty(input.poster)) {\n            this.poster = input.poster;\n          }\n\n          if (this.config.loop.active) {\n            this.media.setAttribute('loop', '');\n          }\n\n          if (this.config.muted) {\n            this.media.setAttribute('muted', '');\n          }\n\n          if (this.config.playsinline) {\n            this.media.setAttribute('playsinline', '');\n          }\n        } // Restore class hook\n\n\n        ui.addStyleHook.call(this); // Set new sources for html5\n\n        if (this.isHTML5) {\n          source.insertElements.call(this, 'source', sources);\n        } // Set video title\n\n\n        this.config.title = input.title; // Set up from scratch\n\n        media.setup.call(this); // HTML5 stuff\n\n        if (this.isHTML5) {\n          // Setup captions\n          if (Object.keys(input).includes('tracks')) {\n            source.insertElements.call(this, 'track', input.tracks);\n          }\n        } // If HTML5 or embed but not fully supported, setupInterface and call ready now\n\n\n        if (this.isHTML5 || this.isEmbed && !this.supported.ui) {\n          // Setup interface\n          ui.build.call(this);\n        } // Load HTML5 sources\n\n\n        if (this.isHTML5) {\n          this.media.load();\n        } // Update previewThumbnails config & reload plugin\n\n\n        if (!is.empty(input.previewThumbnails)) {\n          Object.assign(this.config.previewThumbnails, input.previewThumbnails); // Cleanup previewThumbnails plugin if it was loaded\n\n          if (this.previewThumbnails && this.previewThumbnails.loaded) {\n            this.previewThumbnails.destroy();\n            this.previewThumbnails = null;\n          } // Create new instance if it is still enabled\n\n\n          if (this.config.previewThumbnails.enabled) {\n            this.previewThumbnails = new PreviewThumbnails(this);\n          }\n        } // Update the fullscreen support\n\n\n        this.fullscreen.update();\n      }, true);\n    }\n\n  };\n\n  /**\n   * Returns a number whose value is limited to the given range.\n   *\n   * Example: limit the output of this computation to between 0 and 255\n   * (x * 255).clamp(0, 255)\n   *\n   * @param {Number} input\n   * @param {Number} min The lower boundary of the output range\n   * @param {Number} max The upper boundary of the output range\n   * @returns A number in the range [min, max]\n   * @type Number\n   */\n  function clamp(input = 0, min = 0, max = 255) {\n    return Math.min(Math.max(input, min), max);\n  }\n\n  // TODO: Use a WeakMap for private globals\n  // const globals = new WeakMap();\n  // Plyr instance\n\n  class Plyr {\n    constructor(target, options) {\n      _defineProperty$1(this, \"play\", () => {\n        if (!is.function(this.media.play)) {\n          return null;\n        } // Intecept play with ads\n\n\n        if (this.ads && this.ads.enabled) {\n          this.ads.managerPromise.then(() => this.ads.play()).catch(() => silencePromise(this.media.play()));\n        } // Return the promise (for HTML5)\n\n\n        return this.media.play();\n      });\n\n      _defineProperty$1(this, \"pause\", () => {\n        if (!this.playing || !is.function(this.media.pause)) {\n          return null;\n        }\n\n        return this.media.pause();\n      });\n\n      _defineProperty$1(this, \"togglePlay\", input => {\n        // Toggle based on current state if nothing passed\n        const toggle = is.boolean(input) ? input : !this.playing;\n\n        if (toggle) {\n          return this.play();\n        }\n\n        return this.pause();\n      });\n\n      _defineProperty$1(this, \"stop\", () => {\n        if (this.isHTML5) {\n          this.pause();\n          this.restart();\n        } else if (is.function(this.media.stop)) {\n          this.media.stop();\n        }\n      });\n\n      _defineProperty$1(this, \"restart\", () => {\n        this.currentTime = 0;\n      });\n\n      _defineProperty$1(this, \"rewind\", seekTime => {\n        this.currentTime -= is.number(seekTime) ? seekTime : this.config.seekTime;\n      });\n\n      _defineProperty$1(this, \"forward\", seekTime => {\n        this.currentTime += is.number(seekTime) ? seekTime : this.config.seekTime;\n      });\n\n      _defineProperty$1(this, \"increaseVolume\", step => {\n        const volume = this.media.muted ? 0 : this.volume;\n        this.volume = volume + (is.number(step) ? step : 0);\n      });\n\n      _defineProperty$1(this, \"decreaseVolume\", step => {\n        this.increaseVolume(-step);\n      });\n\n      _defineProperty$1(this, \"airplay\", () => {\n        // Show dialog if supported\n        if (support.airplay) {\n          this.media.webkitShowPlaybackTargetPicker();\n        }\n      });\n\n      _defineProperty$1(this, \"toggleControls\", toggle => {\n        // Don't toggle if missing UI support or if it's audio\n        if (this.supported.ui && !this.isAudio) {\n          // Get state before change\n          const isHidden = hasClass(this.elements.container, this.config.classNames.hideControls); // Negate the argument if not undefined since adding the class to hides the controls\n\n          const force = typeof toggle === 'undefined' ? undefined : !toggle; // Apply and get updated state\n\n          const hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force); // Close menu\n\n          if (hiding && is.array(this.config.controls) && this.config.controls.includes('settings') && !is.empty(this.config.settings)) {\n            controls.toggleMenu.call(this, false);\n          } // Trigger event on change\n\n\n          if (hiding !== isHidden) {\n            const eventName = hiding ? 'controlshidden' : 'controlsshown';\n            triggerEvent.call(this, this.media, eventName);\n          }\n\n          return !hiding;\n        }\n\n        return false;\n      });\n\n      _defineProperty$1(this, \"on\", (event, callback) => {\n        on.call(this, this.elements.container, event, callback);\n      });\n\n      _defineProperty$1(this, \"once\", (event, callback) => {\n        once.call(this, this.elements.container, event, callback);\n      });\n\n      _defineProperty$1(this, \"off\", (event, callback) => {\n        off(this.elements.container, event, callback);\n      });\n\n      _defineProperty$1(this, \"destroy\", (callback, soft = false) => {\n        if (!this.ready) {\n          return;\n        }\n\n        const done = () => {\n          // Reset overflow (incase destroyed while in fullscreen)\n          document.body.style.overflow = ''; // GC for embed\n\n          this.embed = null; // If it's a soft destroy, make minimal changes\n\n          if (soft) {\n            if (Object.keys(this.elements).length) {\n              // Remove elements\n              removeElement(this.elements.buttons.play);\n              removeElement(this.elements.captions);\n              removeElement(this.elements.controls);\n              removeElement(this.elements.wrapper); // Clear for GC\n\n              this.elements.buttons.play = null;\n              this.elements.captions = null;\n              this.elements.controls = null;\n              this.elements.wrapper = null;\n            } // Callback\n\n\n            if (is.function(callback)) {\n              callback();\n            }\n          } else {\n            // Unbind listeners\n            unbindListeners.call(this); // Cancel current network requests\n\n            html5.cancelRequests.call(this); // Replace the container with the original element provided\n\n            replaceElement(this.elements.original, this.elements.container); // Event\n\n            triggerEvent.call(this, this.elements.original, 'destroyed', true); // Callback\n\n            if (is.function(callback)) {\n              callback.call(this.elements.original);\n            } // Reset state\n\n\n            this.ready = false; // Clear for garbage collection\n\n            setTimeout(() => {\n              this.elements = null;\n              this.media = null;\n            }, 200);\n          }\n        }; // Stop playback\n\n\n        this.stop(); // Clear timeouts\n\n        clearTimeout(this.timers.loading);\n        clearTimeout(this.timers.controls);\n        clearTimeout(this.timers.resized); // Provider specific stuff\n\n        if (this.isHTML5) {\n          // Restore native video controls\n          ui.toggleNativeControls.call(this, true); // Clean up\n\n          done();\n        } else if (this.isYouTube) {\n          // Clear timers\n          clearInterval(this.timers.buffering);\n          clearInterval(this.timers.playing); // Destroy YouTube API\n\n          if (this.embed !== null && is.function(this.embed.destroy)) {\n            this.embed.destroy();\n          } // Clean up\n\n\n          done();\n        } else if (this.isVimeo) {\n          // Destroy Vimeo API\n          // then clean up (wait, to prevent postmessage errors)\n          if (this.embed !== null) {\n            this.embed.unload().then(done);\n          } // Vimeo does not always return\n\n\n          setTimeout(done, 200);\n        }\n      });\n\n      _defineProperty$1(this, \"supports\", type => support.mime.call(this, type));\n\n      this.timers = {}; // State\n\n      this.ready = false;\n      this.loading = false;\n      this.failed = false; // Touch device\n\n      this.touch = support.touch; // Set the media element\n\n      this.media = target; // String selector passed\n\n      if (is.string(this.media)) {\n        this.media = document.querySelectorAll(this.media);\n      } // jQuery, NodeList or Array passed, use first element\n\n\n      if (window.jQuery && this.media instanceof jQuery || is.nodeList(this.media) || is.array(this.media)) {\n        // eslint-disable-next-line\n        this.media = this.media[0];\n      } // Set config\n\n\n      this.config = extend({}, defaults, Plyr.defaults, options || {}, (() => {\n        try {\n          return JSON.parse(this.media.getAttribute('data-plyr-config'));\n        } catch (_) {\n          return {};\n        }\n      })()); // Elements cache\n\n      this.elements = {\n        container: null,\n        fullscreen: null,\n        captions: null,\n        buttons: {},\n        display: {},\n        progress: {},\n        inputs: {},\n        settings: {\n          popup: null,\n          menu: null,\n          panels: {},\n          buttons: {}\n        }\n      }; // Captions\n\n      this.captions = {\n        active: null,\n        currentTrack: -1,\n        meta: new WeakMap()\n      }; // Fullscreen\n\n      this.fullscreen = {\n        active: false\n      }; // Options\n\n      this.options = {\n        speed: [],\n        quality: []\n      }; // Debugging\n      // TODO: move to globals\n\n      this.debug = new Console(this.config.debug); // Log config options and support\n\n      this.debug.log('Config', this.config);\n      this.debug.log('Support', support); // We need an element to setup\n\n      if (is.nullOrUndefined(this.media) || !is.element(this.media)) {\n        this.debug.error('Setup failed: no suitable element passed');\n        return;\n      } // Bail if the element is initialized\n\n\n      if (this.media.plyr) {\n        this.debug.warn('Target already setup');\n        return;\n      } // Bail if not enabled\n\n\n      if (!this.config.enabled) {\n        this.debug.error('Setup failed: disabled by config');\n        return;\n      } // Bail if disabled or no basic support\n      // You may want to disable certain UAs etc\n\n\n      if (!support.check().api) {\n        this.debug.error('Setup failed: no support');\n        return;\n      } // Cache original element state for .destroy()\n\n\n      const clone = this.media.cloneNode(true);\n      clone.autoplay = false;\n      this.elements.original = clone; // Set media type based on tag or data attribute\n      // Supported: video, audio, vimeo, youtube\n\n      const _type = this.media.tagName.toLowerCase(); // Embed properties\n\n\n      let iframe = null;\n      let url = null; // Different setup based on type\n\n      switch (_type) {\n        case 'div':\n          // Find the frame\n          iframe = this.media.querySelector('iframe'); // <iframe> type\n\n          if (is.element(iframe)) {\n            // Detect provider\n            url = parseUrl(iframe.getAttribute('src'));\n            this.provider = getProviderByUrl(url.toString()); // Rework elements\n\n            this.elements.container = this.media;\n            this.media = iframe; // Reset classname\n\n            this.elements.container.className = ''; // Get attributes from URL and set config\n\n            if (url.search.length) {\n              const truthy = ['1', 'true'];\n\n              if (truthy.includes(url.searchParams.get('autoplay'))) {\n                this.config.autoplay = true;\n              }\n\n              if (truthy.includes(url.searchParams.get('loop'))) {\n                this.config.loop.active = true;\n              } // TODO: replace fullscreen.iosNative with this playsinline config option\n              // YouTube requires the playsinline in the URL\n\n\n              if (this.isYouTube) {\n                this.config.playsinline = truthy.includes(url.searchParams.get('playsinline'));\n                this.config.youtube.hl = url.searchParams.get('hl'); // TODO: Should this be setting language?\n              } else {\n                this.config.playsinline = true;\n              }\n            }\n          } else {\n            // <div> with attributes\n            this.provider = this.media.getAttribute(this.config.attributes.embed.provider); // Remove attribute\n\n            this.media.removeAttribute(this.config.attributes.embed.provider);\n          } // Unsupported or missing provider\n\n\n          if (is.empty(this.provider) || !Object.values(providers).includes(this.provider)) {\n            this.debug.error('Setup failed: Invalid provider');\n            return;\n          } // Audio will come later for external providers\n\n\n          this.type = types.video;\n          break;\n\n        case 'video':\n        case 'audio':\n          this.type = _type;\n          this.provider = providers.html5; // Get config from attributes\n\n          if (this.media.hasAttribute('crossorigin')) {\n            this.config.crossorigin = true;\n          }\n\n          if (this.media.hasAttribute('autoplay')) {\n            this.config.autoplay = true;\n          }\n\n          if (this.media.hasAttribute('playsinline') || this.media.hasAttribute('webkit-playsinline')) {\n            this.config.playsinline = true;\n          }\n\n          if (this.media.hasAttribute('muted')) {\n            this.config.muted = true;\n          }\n\n          if (this.media.hasAttribute('loop')) {\n            this.config.loop.active = true;\n          }\n\n          break;\n\n        default:\n          this.debug.error('Setup failed: unsupported type');\n          return;\n      } // Check for support again but with type\n\n\n      this.supported = support.check(this.type, this.provider, this.config.playsinline); // If no support for even API, bail\n\n      if (!this.supported.api) {\n        this.debug.error('Setup failed: no support');\n        return;\n      }\n\n      this.eventListeners = []; // Create listeners\n\n      this.listeners = new Listeners(this); // Setup local storage for user settings\n\n      this.storage = new Storage(this); // Store reference\n\n      this.media.plyr = this; // Wrap media\n\n      if (!is.element(this.elements.container)) {\n        this.elements.container = createElement('div', {\n          tabindex: 0\n        });\n        wrap(this.media, this.elements.container);\n      } // Migrate custom properties from media to container (so they work \uD83D\uDE09)\n\n\n      ui.migrateStyles.call(this); // Add style hook\n\n      ui.addStyleHook.call(this); // Setup media\n\n      media.setup.call(this); // Listen for events if debugging\n\n      if (this.config.debug) {\n        on.call(this, this.elements.container, this.config.events.join(' '), event => {\n          this.debug.log(`event: ${event.type}`);\n        });\n      } // Setup fullscreen\n\n\n      this.fullscreen = new Fullscreen(this); // Setup interface\n      // If embed but not fully supported, build interface now to avoid flash of controls\n\n      if (this.isHTML5 || this.isEmbed && !this.supported.ui) {\n        ui.build.call(this);\n      } // Container listeners\n\n\n      this.listeners.container(); // Global listeners\n\n      this.listeners.global(); // Setup ads if provided\n\n      if (this.config.ads.enabled) {\n        this.ads = new Ads(this);\n      } // Autoplay if required\n\n\n      if (this.isHTML5 && this.config.autoplay) {\n        this.once('canplay', () => silencePromise(this.play()));\n      } // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek\n\n\n      this.lastSeekTime = 0; // Setup preview thumbnails if enabled\n\n      if (this.config.previewThumbnails.enabled) {\n        this.previewThumbnails = new PreviewThumbnails(this);\n      }\n    } // ---------------------------------------\n    // API\n    // ---------------------------------------\n\n    /**\n     * Types and provider helpers\n     */\n\n\n    get isHTML5() {\n      return this.provider === providers.html5;\n    }\n\n    get isEmbed() {\n      return this.isYouTube || this.isVimeo;\n    }\n\n    get isYouTube() {\n      return this.provider === providers.youtube;\n    }\n\n    get isVimeo() {\n      return this.provider === providers.vimeo;\n    }\n\n    get isVideo() {\n      return this.type === types.video;\n    }\n\n    get isAudio() {\n      return this.type === types.audio;\n    }\n    /**\n     * Play the media, or play the advertisement (if they are not blocked)\n     */\n\n\n    /**\n     * Get playing state\n     */\n    get playing() {\n      return Boolean(this.ready && !this.paused && !this.ended);\n    }\n    /**\n     * Get paused state\n     */\n\n\n    get paused() {\n      return Boolean(this.media.paused);\n    }\n    /**\n     * Get stopped state\n     */\n\n\n    get stopped() {\n      return Boolean(this.paused && this.currentTime === 0);\n    }\n    /**\n     * Get ended state\n     */\n\n\n    get ended() {\n      return Boolean(this.media.ended);\n    }\n    /**\n     * Toggle playback based on current status\n     * @param {Boolean} input\n     */\n\n\n    /**\n     * Seek to a time\n     * @param {Number} input - where to seek to in seconds. Defaults to 0 (the start)\n     */\n    set currentTime(input) {\n      // Bail if media duration isn't available yet\n      if (!this.duration) {\n        return;\n      } // Validate input\n\n\n      const inputIsValid = is.number(input) && input > 0; // Set\n\n      this.media.currentTime = inputIsValid ? Math.min(input, this.duration) : 0; // Logging\n\n      this.debug.log(`Seeking to ${this.currentTime} seconds`);\n    }\n    /**\n     * Get current time\n     */\n\n\n    get currentTime() {\n      return Number(this.media.currentTime);\n    }\n    /**\n     * Get buffered\n     */\n\n\n    get buffered() {\n      const {\n        buffered\n      } = this.media; // YouTube / Vimeo return a float between 0-1\n\n      if (is.number(buffered)) {\n        return buffered;\n      } // HTML5\n      // TODO: Handle buffered chunks of the media\n      // (i.e. seek to another section buffers only that section)\n\n\n      if (buffered && buffered.length && this.duration > 0) {\n        return buffered.end(0) / this.duration;\n      }\n\n      return 0;\n    }\n    /**\n     * Get seeking status\n     */\n\n\n    get seeking() {\n      return Boolean(this.media.seeking);\n    }\n    /**\n     * Get the duration of the current media\n     */\n\n\n    get duration() {\n      // Faux duration set via config\n      const fauxDuration = parseFloat(this.config.duration); // Media duration can be NaN or Infinity before the media has loaded\n\n      const realDuration = (this.media || {}).duration;\n      const duration = !is.number(realDuration) || realDuration === Infinity ? 0 : realDuration; // If config duration is funky, use regular duration\n\n      return fauxDuration || duration;\n    }\n    /**\n     * Set the player volume\n     * @param {Number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage\n     */\n\n\n    set volume(value) {\n      let volume = value;\n      const max = 1;\n      const min = 0;\n\n      if (is.string(volume)) {\n        volume = Number(volume);\n      } // Load volume from storage if no value specified\n\n\n      if (!is.number(volume)) {\n        volume = this.storage.get('volume');\n      } // Use config if all else fails\n\n\n      if (!is.number(volume)) {\n        ({\n          volume\n        } = this.config);\n      } // Maximum is volumeMax\n\n\n      if (volume > max) {\n        volume = max;\n      } // Minimum is volumeMin\n\n\n      if (volume < min) {\n        volume = min;\n      } // Update config\n\n\n      this.config.volume = volume; // Set the player volume\n\n      this.media.volume = volume; // If muted, and we're increasing volume manually, reset muted state\n\n      if (!is.empty(value) && this.muted && volume > 0) {\n        this.muted = false;\n      }\n    }\n    /**\n     * Get the current player volume\n     */\n\n\n    get volume() {\n      return Number(this.media.volume);\n    }\n    /**\n     * Increase volume\n     * @param {Boolean} step - How much to decrease by (between 0 and 1)\n     */\n\n\n    /**\n     * Set muted state\n     * @param {Boolean} mute\n     */\n    set muted(mute) {\n      let toggle = mute; // Load muted state from storage\n\n      if (!is.boolean(toggle)) {\n        toggle = this.storage.get('muted');\n      } // Use config if all else fails\n\n\n      if (!is.boolean(toggle)) {\n        toggle = this.config.muted;\n      } // Update config\n\n\n      this.config.muted = toggle; // Set mute on the player\n\n      this.media.muted = toggle;\n    }\n    /**\n     * Get current muted state\n     */\n\n\n    get muted() {\n      return Boolean(this.media.muted);\n    }\n    /**\n     * Check if the media has audio\n     */\n\n\n    get hasAudio() {\n      // Assume yes for all non HTML5 (as we can't tell...)\n      if (!this.isHTML5) {\n        return true;\n      }\n\n      if (this.isAudio) {\n        return true;\n      } // Get audio tracks\n\n\n      return Boolean(this.media.mozHasAudio) || Boolean(this.media.webkitAudioDecodedByteCount) || Boolean(this.media.audioTracks && this.media.audioTracks.length);\n    }\n    /**\n     * Set playback speed\n     * @param {Number} speed - the speed of playback (0.5-2.0)\n     */\n\n\n    set speed(input) {\n      let speed = null;\n\n      if (is.number(input)) {\n        speed = input;\n      }\n\n      if (!is.number(speed)) {\n        speed = this.storage.get('speed');\n      }\n\n      if (!is.number(speed)) {\n        speed = this.config.speed.selected;\n      } // Clamp to min/max\n\n\n      const {\n        minimumSpeed: min,\n        maximumSpeed: max\n      } = this;\n      speed = clamp(speed, min, max); // Update config\n\n      this.config.speed.selected = speed; // Set media speed\n\n      setTimeout(() => {\n        if (this.media) {\n          this.media.playbackRate = speed;\n        }\n      }, 0);\n    }\n    /**\n     * Get current playback speed\n     */\n\n\n    get speed() {\n      return Number(this.media.playbackRate);\n    }\n    /**\n     * Get the minimum allowed speed\n     */\n\n\n    get minimumSpeed() {\n      if (this.isYouTube) {\n        // https://developers.google.com/youtube/iframe_api_reference#setPlaybackRate\n        return Math.min(...this.options.speed);\n      }\n\n      if (this.isVimeo) {\n        // https://github.com/vimeo/player.js/#setplaybackrateplaybackrate-number-promisenumber-rangeerrorerror\n        return 0.5;\n      } // https://stackoverflow.com/a/32320020/1191319\n\n\n      return 0.0625;\n    }\n    /**\n     * Get the maximum allowed speed\n     */\n\n\n    get maximumSpeed() {\n      if (this.isYouTube) {\n        // https://developers.google.com/youtube/iframe_api_reference#setPlaybackRate\n        return Math.max(...this.options.speed);\n      }\n\n      if (this.isVimeo) {\n        // https://github.com/vimeo/player.js/#setplaybackrateplaybackrate-number-promisenumber-rangeerrorerror\n        return 2;\n      } // https://stackoverflow.com/a/32320020/1191319\n\n\n      return 16;\n    }\n    /**\n     * Set playback quality\n     * Currently HTML5 & YouTube only\n     * @param {Number} input - Quality level\n     */\n\n\n    set quality(input) {\n      const config = this.config.quality;\n      const options = this.options.quality;\n\n      if (!options.length) {\n        return;\n      }\n\n      let quality = [!is.empty(input) && Number(input), this.storage.get('quality'), config.selected, config.default].find(is.number);\n      let updateStorage = true;\n\n      if (!options.includes(quality)) {\n        const value = closest(options, quality);\n        this.debug.warn(`Unsupported quality option: ${quality}, using ${value} instead`);\n        quality = value; // Don't update storage if quality is not supported\n\n        updateStorage = false;\n      } // Update config\n\n\n      config.selected = quality; // Set quality\n\n      this.media.quality = quality; // Save to storage\n\n      if (updateStorage) {\n        this.storage.set({\n          quality\n        });\n      }\n    }\n    /**\n     * Get current quality level\n     */\n\n\n    get quality() {\n      return this.media.quality;\n    }\n    /**\n     * Toggle loop\n     * TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config\n     * @param {Boolean} input - Whether to loop or not\n     */\n\n\n    set loop(input) {\n      const toggle = is.boolean(input) ? input : this.config.loop.active;\n      this.config.loop.active = toggle;\n      this.media.loop = toggle; // Set default to be a true toggle\n\n      /* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle';\n           switch (type) {\n              case 'start':\n                  if (this.config.loop.end && this.config.loop.end <= this.currentTime) {\n                      this.config.loop.end = null;\n                  }\n                  this.config.loop.start = this.currentTime;\n                  // this.config.loop.indicator.start = this.elements.display.played.value;\n                  break;\n               case 'end':\n                  if (this.config.loop.start >= this.currentTime) {\n                      return this;\n                  }\n                  this.config.loop.end = this.currentTime;\n                  // this.config.loop.indicator.end = this.elements.display.played.value;\n                  break;\n               case 'all':\n                  this.config.loop.start = 0;\n                  this.config.loop.end = this.duration - 2;\n                  this.config.loop.indicator.start = 0;\n                  this.config.loop.indicator.end = 100;\n                  break;\n               case 'toggle':\n                  if (this.config.loop.active) {\n                      this.config.loop.start = 0;\n                      this.config.loop.end = null;\n                  } else {\n                      this.config.loop.start = 0;\n                      this.config.loop.end = this.duration - 2;\n                  }\n                  break;\n               default:\n                  this.config.loop.start = 0;\n                  this.config.loop.end = null;\n                  break;\n          } */\n    }\n    /**\n     * Get current loop state\n     */\n\n\n    get loop() {\n      return Boolean(this.media.loop);\n    }\n    /**\n     * Set new media source\n     * @param {Object} input - The new source object (see docs)\n     */\n\n\n    set source(input) {\n      source.change.call(this, input);\n    }\n    /**\n     * Get current source\n     */\n\n\n    get source() {\n      return this.media.currentSrc;\n    }\n    /**\n     * Get a download URL (either source or custom)\n     */\n\n\n    get download() {\n      const {\n        download\n      } = this.config.urls;\n      return is.url(download) ? download : this.source;\n    }\n    /**\n     * Set the download URL\n     */\n\n\n    set download(input) {\n      if (!is.url(input)) {\n        return;\n      }\n\n      this.config.urls.download = input;\n      controls.setDownloadUrl.call(this);\n    }\n    /**\n     * Set the poster image for a video\n     * @param {String} input - the URL for the new poster image\n     */\n\n\n    set poster(input) {\n      if (!this.isVideo) {\n        this.debug.warn('Poster can only be set for video');\n        return;\n      }\n\n      ui.setPoster.call(this, input, false).catch(() => {});\n    }\n    /**\n     * Get the current poster image\n     */\n\n\n    get poster() {\n      if (!this.isVideo) {\n        return null;\n      }\n\n      return this.media.getAttribute('poster') || this.media.getAttribute('data-poster');\n    }\n    /**\n     * Get the current aspect ratio in use\n     */\n\n\n    get ratio() {\n      if (!this.isVideo) {\n        return null;\n      }\n\n      const ratio = reduceAspectRatio(getAspectRatio.call(this));\n      return is.array(ratio) ? ratio.join(':') : ratio;\n    }\n    /**\n     * Set video aspect ratio\n     */\n\n\n    set ratio(input) {\n      if (!this.isVideo) {\n        this.debug.warn('Aspect ratio can only be set for video');\n        return;\n      }\n\n      if (!is.string(input) || !validateAspectRatio(input)) {\n        this.debug.error(`Invalid aspect ratio specified (${input})`);\n        return;\n      }\n\n      this.config.ratio = reduceAspectRatio(input);\n      setAspectRatio.call(this);\n    }\n    /**\n     * Set the autoplay state\n     * @param {Boolean} input - Whether to autoplay or not\n     */\n\n\n    set autoplay(input) {\n      const toggle = is.boolean(input) ? input : this.config.autoplay;\n      this.config.autoplay = toggle;\n    }\n    /**\n     * Get the current autoplay state\n     */\n\n\n    get autoplay() {\n      return Boolean(this.config.autoplay);\n    }\n    /**\n     * Toggle captions\n     * @param {Boolean} input - Whether to enable captions\n     */\n\n\n    toggleCaptions(input) {\n      captions.toggle.call(this, input, false);\n    }\n    /**\n     * Set the caption track by index\n     * @param {Number} - Caption index\n     */\n\n\n    set currentTrack(input) {\n      captions.set.call(this, input, false);\n      captions.setup();\n    }\n    /**\n     * Get the current caption track index (-1 if disabled)\n     */\n\n\n    get currentTrack() {\n      const {\n        toggled,\n        currentTrack\n      } = this.captions;\n      return toggled ? currentTrack : -1;\n    }\n    /**\n     * Set the wanted language for captions\n     * Since tracks can be added later it won't update the actual caption track until there is a matching track\n     * @param {String} - Two character ISO language code (e.g. EN, FR, PT, etc)\n     */\n\n\n    set language(input) {\n      captions.setLanguage.call(this, input, false);\n    }\n    /**\n     * Get the current track's language\n     */\n\n\n    get language() {\n      return (captions.getCurrentTrack.call(this) || {}).language;\n    }\n    /**\n     * Toggle picture-in-picture playback on WebKit/MacOS\n     * TODO: update player with state, support, enabled\n     * TODO: detect outside changes\n     */\n\n\n    set pip(input) {\n      // Bail if no support\n      if (!support.pip) {\n        return;\n      } // Toggle based on current state if not passed\n\n\n      const toggle = is.boolean(input) ? input : !this.pip; // Toggle based on current state\n      // Safari\n\n      if (is.function(this.media.webkitSetPresentationMode)) {\n        this.media.webkitSetPresentationMode(toggle ? pip.active : pip.inactive);\n      } // Chrome\n\n\n      if (is.function(this.media.requestPictureInPicture)) {\n        if (!this.pip && toggle) {\n          this.media.requestPictureInPicture();\n        } else if (this.pip && !toggle) {\n          document.exitPictureInPicture();\n        }\n      }\n    }\n    /**\n     * Get the current picture-in-picture state\n     */\n\n\n    get pip() {\n      if (!support.pip) {\n        return null;\n      } // Safari\n\n\n      if (!is.empty(this.media.webkitPresentationMode)) {\n        return this.media.webkitPresentationMode === pip.active;\n      } // Chrome\n\n\n      return this.media === document.pictureInPictureElement;\n    }\n    /**\n     * Sets the preview thubmnails for the current source\n     */\n\n\n    setPreviewThumbnails(thumbnailSource) {\n      if (this.previewThumbnails && this.previewThumbnails.loaded) {\n        this.previewThumbnails.destroy();\n        this.previewThumbnails = null;\n      }\n\n      Object.assign(this.config.previewThumbnails, thumbnailSource); // Create new instance if it is still enabled\n\n      if (this.config.previewThumbnails.enabled) {\n        this.previewThumbnails = new PreviewThumbnails(this);\n      }\n    }\n    /**\n     * Trigger the airplay dialog\n     * TODO: update player with state, support, enabled\n     */\n\n\n    /**\n     * Check for support\n     * @param {String} type - Player type (audio/video)\n     * @param {String} provider - Provider (html5/youtube/vimeo)\n     * @param {Boolean} inline - Where player has `playsinline` sttribute\n     */\n    static supported(type, provider, inline) {\n      return support.check(type, provider, inline);\n    }\n    /**\n     * Load an SVG sprite into the page\n     * @param {String} url - URL for the SVG sprite\n     * @param {String} [id] - Unique ID\n     */\n\n\n    static loadSprite(url, id) {\n      return loadSprite(url, id);\n    }\n    /**\n     * Setup multiple instances\n     * @param {*} selector\n     * @param {Object} options\n     */\n\n\n    static setup(selector, options = {}) {\n      let targets = null;\n\n      if (is.string(selector)) {\n        targets = Array.from(document.querySelectorAll(selector));\n      } else if (is.nodeList(selector)) {\n        targets = Array.from(selector);\n      } else if (is.array(selector)) {\n        targets = selector.filter(is.element);\n      }\n\n      if (is.empty(targets)) {\n        return null;\n      }\n\n      return targets.map(t => new Plyr(t, options));\n    }\n\n  }\n\n  Plyr.defaults = cloneDeep(defaults);\n\n  return Plyr;\n\n}));\n", "function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError(\"Cannot call a class as a function\")}function _defineProperties(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,\"value\"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function _createClass(e,t,n){return t&&_defineProperties(e.prototype,t),n&&_defineProperties(e,n),e}function _defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function ownKeys(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function _objectSpread2(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?ownKeys(Object(n),!0).forEach((function(t){_defineProperty(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):ownKeys(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}var defaults={addCSS:!0,thumbWidth:15,watch:!0};function matches(e,t){return function(){return Array.from(document.querySelectorAll(t)).includes(this)}.call(e,t)}function trigger(e,t){if(e&&t){var n=new Event(t,{bubbles:!0});e.dispatchEvent(n)}}var getConstructor=function(e){return null!=e?e.constructor:null},instanceOf=function(e,t){return!!(e&&t&&e instanceof t)},isNullOrUndefined=function(e){return null==e},isObject=function(e){return getConstructor(e)===Object},isNumber=function(e){return getConstructor(e)===Number&&!Number.isNaN(e)},isString=function(e){return getConstructor(e)===String},isBoolean=function(e){return getConstructor(e)===Boolean},isFunction=function(e){return getConstructor(e)===Function},isArray=function(e){return Array.isArray(e)},isNodeList=function(e){return instanceOf(e,NodeList)},isElement=function(e){return instanceOf(e,Element)},isEvent=function(e){return instanceOf(e,Event)},isEmpty=function(e){return isNullOrUndefined(e)||(isString(e)||isArray(e)||isNodeList(e))&&!e.length||isObject(e)&&!Object.keys(e).length},is={nullOrUndefined:isNullOrUndefined,object:isObject,number:isNumber,string:isString,boolean:isBoolean,function:isFunction,array:isArray,nodeList:isNodeList,element:isElement,event:isEvent,empty:isEmpty};function getDecimalPlaces(e){var t=\"\".concat(e).match(/(?:\\.(\\d+))?(?:[eE]([+-]?\\d+))?$/);return t?Math.max(0,(t[1]?t[1].length:0)-(t[2]?+t[2]:0)):0}function round(e,t){if(1>t){var n=getDecimalPlaces(t);return parseFloat(e.toFixed(n))}return Math.round(e/t)*t}var RangeTouch=function(){function e(t,n){_classCallCheck(this,e),is.element(t)?this.element=t:is.string(t)&&(this.element=document.querySelector(t)),is.element(this.element)&&is.empty(this.element.rangeTouch)&&(this.config=_objectSpread2({},defaults,{},n),this.init())}return _createClass(e,[{key:\"init\",value:function(){e.enabled&&(this.config.addCSS&&(this.element.style.userSelect=\"none\",this.element.style.webKitUserSelect=\"none\",this.element.style.touchAction=\"manipulation\"),this.listeners(!0),this.element.rangeTouch=this)}},{key:\"destroy\",value:function(){e.enabled&&(this.config.addCSS&&(this.element.style.userSelect=\"\",this.element.style.webKitUserSelect=\"\",this.element.style.touchAction=\"\"),this.listeners(!1),this.element.rangeTouch=null)}},{key:\"listeners\",value:function(e){var t=this,n=e?\"addEventListener\":\"removeEventListener\";[\"touchstart\",\"touchmove\",\"touchend\"].forEach((function(e){t.element[n](e,(function(e){return t.set(e)}),!1)}))}},{key:\"get\",value:function(t){if(!e.enabled||!is.event(t))return null;var n,r=t.target,i=t.changedTouches[0],o=parseFloat(r.getAttribute(\"min\"))||0,s=parseFloat(r.getAttribute(\"max\"))||100,u=parseFloat(r.getAttribute(\"step\"))||1,c=r.getBoundingClientRect(),a=100/c.width*(this.config.thumbWidth/2)/100;return 0>(n=100/c.width*(i.clientX-c.left))?n=0:100<n&&(n=100),50>n?n-=(100-2*n)*a:50<n&&(n+=2*(n-50)*a),o+round(n/100*(s-o),u)}},{key:\"set\",value:function(t){e.enabled&&is.event(t)&&!t.target.disabled&&(t.preventDefault(),t.target.value=this.get(t),trigger(t.target,\"touchend\"===t.type?\"change\":\"input\"))}}],[{key:\"setup\",value:function(t){var n=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{},r=null;if(is.empty(t)||is.string(t)?r=Array.from(document.querySelectorAll(is.string(t)?t:'input[type=\"range\"]')):is.element(t)?r=[t]:is.nodeList(t)?r=Array.from(t):is.array(t)&&(r=t.filter(is.element)),is.empty(r))return null;var i=_objectSpread2({},defaults,{},n);if(is.string(t)&&i.watch){var o=new MutationObserver((function(n){Array.from(n).forEach((function(n){Array.from(n.addedNodes).forEach((function(n){is.element(n)&&matches(n,t)&&new e(n,i)}))}))}));o.observe(document.body,{childList:!0,subtree:!0})}return r.map((function(t){return new e(t,n)}))}},{key:\"enabled\",get:function(){return\"ontouchstart\"in document.documentElement}}]),e}();export default RangeTouch;", "// ==========================================================================\n// Type checking utils\n// ==========================================================================\n\nconst getConstructor = (input) => (input !== null && typeof input !== 'undefined' ? input.constructor : null);\nconst instanceOf = (input, constructor) => Boolean(input && constructor && input instanceof constructor);\nconst isNullOrUndefined = (input) => input === null || typeof input === 'undefined';\nconst isObject = (input) => getConstructor(input) === Object;\nconst isNumber = (input) => getConstructor(input) === Number && !Number.isNaN(input);\nconst isString = (input) => getConstructor(input) === String;\nconst isBoolean = (input) => getConstructor(input) === Boolean;\nconst isFunction = (input) => getConstructor(input) === Function;\nconst isArray = (input) => Array.isArray(input);\nconst isWeakMap = (input) => instanceOf(input, WeakMap);\nconst isNodeList = (input) => instanceOf(input, NodeList);\nconst isTextNode = (input) => getConstructor(input) === Text;\nconst isEvent = (input) => instanceOf(input, Event);\nconst isKeyboardEvent = (input) => instanceOf(input, KeyboardEvent);\nconst isCue = (input) => instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue);\nconst isTrack = (input) => instanceOf(input, TextTrack) || (!isNullOrUndefined(input) && isString(input.kind));\nconst isPromise = (input) => instanceOf(input, Promise) && isFunction(input.then);\n\nconst isElement = (input) =>\n  input !== null &&\n  typeof input === 'object' &&\n  input.nodeType === 1 &&\n  typeof input.style === 'object' &&\n  typeof input.ownerDocument === 'object';\n\nconst isEmpty = (input) =>\n  isNullOrUndefined(input) ||\n  ((isString(input) || isArray(input) || isNodeList(input)) && !input.length) ||\n  (isObject(input) && !Object.keys(input).length);\n\nconst isUrl = (input) => {\n  // Accept a URL object\n  if (instanceOf(input, window.URL)) {\n    return true;\n  }\n\n  // Must be string from here\n  if (!isString(input)) {\n    return false;\n  }\n\n  // Add the protocol if required\n  let string = input;\n  if (!input.startsWith('http://') || !input.startsWith('https://')) {\n    string = `http://${input}`;\n  }\n\n  try {\n    return !isEmpty(new URL(string).hostname);\n  } catch (_) {\n    return false;\n  }\n};\n\nexport default {\n  nullOrUndefined: isNullOrUndefined,\n  object: isObject,\n  number: isNumber,\n  string: isString,\n  boolean: isBoolean,\n  function: isFunction,\n  array: isArray,\n  weakMap: isWeakMap,\n  nodeList: isNodeList,\n  element: isElement,\n  textNode: isTextNode,\n  event: isEvent,\n  keyboardEvent: isKeyboardEvent,\n  cue: isCue,\n  track: isTrack,\n  promise: isPromise,\n  url: isUrl,\n  empty: isEmpty,\n};\n", "// ==========================================================================\n// Animation utils\n// ==========================================================================\n\nimport is from './is';\n\nexport const transitionEndEvent = (() => {\n  const element = document.createElement('span');\n\n  const events = {\n    WebkitTransition: 'webkitTransitionEnd',\n    MozTransition: 'transitionend',\n    OTransition: 'oTransitionEnd otransitionend',\n    transition: 'transitionend',\n  };\n\n  const type = Object.keys(events).find((event) => element.style[event] !== undefined);\n\n  return is.string(type) ? events[type] : false;\n})();\n\n// Force repaint of element\nexport function repaint(element, delay) {\n  setTimeout(() => {\n    try {\n      // eslint-disable-next-line no-param-reassign\n      element.hidden = true;\n\n      // eslint-disable-next-line no-unused-expressions\n      element.offsetHeight;\n\n      // eslint-disable-next-line no-param-reassign\n      element.hidden = false;\n    } catch (_) {\n      // Do nothing\n    }\n  }, delay);\n}\n", "// ==========================================================================\n// Browser sniffing\n// Unfortunately, due to mixed support, UA sniffing is required\n// ==========================================================================\n\nconst browser = {\n  isIE: Boolean(window.document.documentMode),\n  isEdge: window.navigator.userAgent.includes('Edge'),\n  isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent),\n  isIPhone: /(iPhone|iPod)/gi.test(navigator.platform),\n  isIos:\n    (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1) ||\n    /(iPad|iPhone|iPod)/gi.test(navigator.platform),\n};\n\nexport default browser;\n", "// ==========================================================================\n// Object utils\n// ==========================================================================\n\nimport is from './is';\n\n// Clone nested objects\nexport function cloneDeep(object) {\n  return JSON.parse(JSON.stringify(object));\n}\n\n// Get a nested value in an object\nexport function getDeep(object, path) {\n  return path.split('.').reduce((obj, key) => obj && obj[key], object);\n}\n\n// Deep extend destination object with N more objects\nexport function extend(target = {}, ...sources) {\n  if (!sources.length) {\n    return target;\n  }\n\n  const source = sources.shift();\n\n  if (!is.object(source)) {\n    return target;\n  }\n\n  Object.keys(source).forEach((key) => {\n    if (is.object(source[key])) {\n      if (!Object.keys(target).includes(key)) {\n        Object.assign(target, { [key]: {} });\n      }\n\n      extend(target[key], source[key]);\n    } else {\n      Object.assign(target, { [key]: source[key] });\n    }\n  });\n\n  return extend(target, ...sources);\n}\n", "// ==========================================================================\n// Element utils\n// ==========================================================================\n\nimport is from './is';\nimport { extend } from './objects';\n\n// Wrap an element\nexport function wrap(elements, wrapper) {\n  // Convert `elements` to an array, if necessary.\n  const targets = elements.length ? elements : [elements];\n\n  // Loops backwards to prevent having to clone the wrapper on the\n  // first element (see `child` below).\n  Array.from(targets)\n    .reverse()\n    .forEach((element, index) => {\n      const child = index > 0 ? wrapper.cloneNode(true) : wrapper;\n      // Cache the current parent and sibling.\n      const parent = element.parentNode;\n      const sibling = element.nextSibling;\n\n      // Wrap the element (is automatically removed from its current\n      // parent).\n      child.appendChild(element);\n\n      // If the element had a sibling, insert the wrapper before\n      // the sibling to maintain the HTML structure; otherwise, just\n      // append it to the parent.\n      if (sibling) {\n        parent.insertBefore(child, sibling);\n      } else {\n        parent.appendChild(child);\n      }\n    });\n}\n\n// Set attributes\nexport function setAttributes(element, attributes) {\n  if (!is.element(element) || is.empty(attributes)) {\n    return;\n  }\n\n  // Assume null and undefined attributes should be left out,\n  // Setting them would otherwise convert them to \"null\" and \"undefined\"\n  Object.entries(attributes)\n    .filter(([, value]) => !is.nullOrUndefined(value))\n    .forEach(([key, value]) => element.setAttribute(key, value));\n}\n\n// Create a DocumentFragment\nexport function createElement(type, attributes, text) {\n  // Create a new <element>\n  const element = document.createElement(type);\n\n  // Set all passed attributes\n  if (is.object(attributes)) {\n    setAttributes(element, attributes);\n  }\n\n  // Add text node\n  if (is.string(text)) {\n    element.innerText = text;\n  }\n\n  // Return built element\n  return element;\n}\n\n// Inaert an element after another\nexport function insertAfter(element, target) {\n  if (!is.element(element) || !is.element(target)) {\n    return;\n  }\n\n  target.parentNode.insertBefore(element, target.nextSibling);\n}\n\n// Insert a DocumentFragment\nexport function insertElement(type, parent, attributes, text) {\n  if (!is.element(parent)) {\n    return;\n  }\n\n  parent.appendChild(createElement(type, attributes, text));\n}\n\n// Remove element(s)\nexport function removeElement(element) {\n  if (is.nodeList(element) || is.array(element)) {\n    Array.from(element).forEach(removeElement);\n    return;\n  }\n\n  if (!is.element(element) || !is.element(element.parentNode)) {\n    return;\n  }\n\n  element.parentNode.removeChild(element);\n}\n\n// Remove all child elements\nexport function emptyElement(element) {\n  if (!is.element(element)) {\n    return;\n  }\n\n  let { length } = element.childNodes;\n\n  while (length > 0) {\n    element.removeChild(element.lastChild);\n    length -= 1;\n  }\n}\n\n// Replace element\nexport function replaceElement(newChild, oldChild) {\n  if (!is.element(oldChild) || !is.element(oldChild.parentNode) || !is.element(newChild)) {\n    return null;\n  }\n\n  oldChild.parentNode.replaceChild(newChild, oldChild);\n\n  return newChild;\n}\n\n// Get an attribute object from a string selector\nexport function getAttributesFromSelector(sel, existingAttributes) {\n  // For example:\n  // '.test' to { class: 'test' }\n  // '#test' to { id: 'test' }\n  // '[data-test=\"test\"]' to { 'data-test': 'test' }\n\n  if (!is.string(sel) || is.empty(sel)) {\n    return {};\n  }\n\n  const attributes = {};\n  const existing = extend({}, existingAttributes);\n\n  sel.split(',').forEach((s) => {\n    // Remove whitespace\n    const selector = s.trim();\n    const className = selector.replace('.', '');\n    const stripped = selector.replace(/[[\\]]/g, '');\n    // Get the parts and value\n    const parts = stripped.split('=');\n    const [key] = parts;\n    const value = parts.length > 1 ? parts[1].replace(/[\"']/g, '') : '';\n    // Get the first character\n    const start = selector.charAt(0);\n\n    switch (start) {\n      case '.':\n        // Add to existing classname\n        if (is.string(existing.class)) {\n          attributes.class = `${existing.class} ${className}`;\n        } else {\n          attributes.class = className;\n        }\n        break;\n\n      case '#':\n        // ID selector\n        attributes.id = selector.replace('#', '');\n        break;\n\n      case '[':\n        // Attribute selector\n        attributes[key] = value;\n\n        break;\n\n      default:\n        break;\n    }\n  });\n\n  return extend(existing, attributes);\n}\n\n// Toggle hidden\nexport function toggleHidden(element, hidden) {\n  if (!is.element(element)) {\n    return;\n  }\n\n  let hide = hidden;\n\n  if (!is.boolean(hide)) {\n    hide = !element.hidden;\n  }\n\n  // eslint-disable-next-line no-param-reassign\n  element.hidden = hide;\n}\n\n// Mirror Element.classList.toggle, with IE compatibility for \"force\" argument\nexport function toggleClass(element, className, force) {\n  if (is.nodeList(element)) {\n    return Array.from(element).map((e) => toggleClass(e, className, force));\n  }\n\n  if (is.element(element)) {\n    let method = 'toggle';\n    if (typeof force !== 'undefined') {\n      method = force ? 'add' : 'remove';\n    }\n\n    element.classList[method](className);\n    return element.classList.contains(className);\n  }\n\n  return false;\n}\n\n// Has class name\nexport function hasClass(element, className) {\n  return is.element(element) && element.classList.contains(className);\n}\n\n// Element matches selector\nexport function matches(element, selector) {\n  const { prototype } = Element;\n\n  function match() {\n    return Array.from(document.querySelectorAll(selector)).includes(this);\n  }\n\n  const method =\n    prototype.matches ||\n    prototype.webkitMatchesSelector ||\n    prototype.mozMatchesSelector ||\n    prototype.msMatchesSelector ||\n    match;\n\n  return method.call(element, selector);\n}\n\n// Closest ancestor element matching selector (also tests element itself)\nexport function closest(element, selector) {\n  const { prototype } = Element;\n\n  // https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill\n  function closestElement() {\n    let el = this;\n\n    do {\n      if (matches.matches(el, selector)) return el;\n      el = el.parentElement || el.parentNode;\n    } while (el !== null && el.nodeType === 1);\n    return null;\n  }\n\n  const method = prototype.closest || closestElement;\n\n  return method.call(element, selector);\n}\n\n// Find all elements\nexport function getElements(selector) {\n  return this.elements.container.querySelectorAll(selector);\n}\n\n// Find a single element\nexport function getElement(selector) {\n  return this.elements.container.querySelector(selector);\n}\n\n// Set focus and tab focus class\nexport function setFocus(element = null, tabFocus = false) {\n  if (!is.element(element)) {\n    return;\n  }\n\n  // Set regular focus\n  element.focus({ preventScroll: true });\n\n  // If we want to mimic keyboard focus via tab\n  if (tabFocus) {\n    toggleClass(element, this.config.classNames.tabFocus);\n  }\n}\n", "// ==========================================================================\n// Plyr support checks\n// ==========================================================================\n\nimport { transitionEndEvent } from './utils/animation';\nimport browser from './utils/browser';\nimport { createElement } from './utils/elements';\nimport is from './utils/is';\n\n// Default codecs for checking mimetype support\nconst defaultCodecs = {\n  'audio/ogg': 'vorbis',\n  'audio/wav': '1',\n  'video/webm': 'vp8, vorbis',\n  'video/mp4': 'avc1.42E01E, mp4a.40.2',\n  'video/ogg': 'theora',\n};\n\n// Check for feature support\nconst support = {\n  // Basic support\n  audio: 'canPlayType' in document.createElement('audio'),\n  video: 'canPlayType' in document.createElement('video'),\n\n  // Check for support\n  // Basic functionality vs full UI\n  check(type, provider, playsinline) {\n    const canPlayInline = browser.isIPhone && playsinline && support.playsinline;\n    const api = support[type] || provider !== 'html5';\n    const ui = api && support.rangeInput && (type !== 'video' || !browser.isIPhone || canPlayInline);\n\n    return {\n      api,\n      ui,\n    };\n  },\n\n  // Picture-in-picture support\n  // Safari & Chrome only currently\n  pip: (() => {\n    if (browser.isIPhone) {\n      return false;\n    }\n\n    // Safari\n    // https://developer.apple.com/documentation/webkitjs/adding_picture_in_picture_to_your_safari_media_controls\n    if (is.function(createElement('video').webkitSetPresentationMode)) {\n      return true;\n    }\n\n    // Chrome\n    // https://developers.google.com/web/updates/2018/10/watch-video-using-picture-in-picture\n    if (document.pictureInPictureEnabled && !createElement('video').disablePictureInPicture) {\n      return true;\n    }\n\n    return false;\n  })(),\n\n  // Airplay support\n  // Safari only currently\n  airplay: is.function(window.WebKitPlaybackTargetAvailabilityEvent),\n\n  // Inline playback support\n  // https://webkit.org/blog/6784/new-video-policies-for-ios/\n  playsinline: 'playsInline' in document.createElement('video'),\n\n  // Check for mime type support against a player instance\n  // Credits: http://diveintohtml5.info/everything.html\n  // Related: http://www.leanbackplayer.com/test/h5mt.html\n  mime(input) {\n    if (is.empty(input)) {\n      return false;\n    }\n\n    const [mediaType] = input.split('/');\n    let type = input;\n\n    // Verify we're using HTML5 and there's no media type mismatch\n    if (!this.isHTML5 || mediaType !== this.type) {\n      return false;\n    }\n\n    // Add codec if required\n    if (Object.keys(defaultCodecs).includes(type)) {\n      type += `; codecs=\"${defaultCodecs[input]}\"`;\n    }\n\n    try {\n      return Boolean(type && this.media.canPlayType(type).replace(/no/, ''));\n    } catch (_) {\n      return false;\n    }\n  },\n\n  // Check for textTracks support\n  textTracks: 'textTracks' in document.createElement('video'),\n\n  // <input type=\"range\"> Sliders\n  rangeInput: (() => {\n    const range = document.createElement('input');\n    range.type = 'range';\n    return range.type === 'range';\n  })(),\n\n  // Touch\n  // NOTE: Remember a device can be mouse + touch enabled so we check on first touch event\n  touch: 'ontouchstart' in document.documentElement,\n\n  // Detect transitions support\n  transitions: transitionEndEvent !== false,\n\n  // Reduced motion iOS & MacOS setting\n  // https://webkit.org/blog/7551/responsive-design-for-motion/\n  reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches,\n};\n\nexport default support;\n", "// ==========================================================================\n// Event utils\n// ==========================================================================\n\nimport is from './is';\n\n// Check for passive event listener support\n// https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md\n// https://www.youtube.com/watch?v=NPM6172J22g\nconst supportsPassiveListeners = (() => {\n  // Test via a getter in the options object to see if the passive property is accessed\n  let supported = false;\n  try {\n    const options = Object.defineProperty({}, 'passive', {\n      get() {\n        supported = true;\n        return null;\n      },\n    });\n    window.addEventListener('test', null, options);\n    window.removeEventListener('test', null, options);\n  } catch (_) {\n    // Do nothing\n  }\n\n  return supported;\n})();\n\n// Toggle event listener\nexport function toggleListener(element, event, callback, toggle = false, passive = true, capture = false) {\n  // Bail if no element, event, or callback\n  if (!element || !('addEventListener' in element) || is.empty(event) || !is.function(callback)) {\n    return;\n  }\n\n  // Allow multiple events\n  const events = event.split(' ');\n  // Build options\n  // Default to just the capture boolean for browsers with no passive listener support\n  let options = capture;\n\n  // If passive events listeners are supported\n  if (supportsPassiveListeners) {\n    options = {\n      // Whether the listener can be passive (i.e. default never prevented)\n      passive,\n      // Whether the listener is a capturing listener or not\n      capture,\n    };\n  }\n\n  // If a single node is passed, bind the event listener\n  events.forEach((type) => {\n    if (this && this.eventListeners && toggle) {\n      // Cache event listener\n      this.eventListeners.push({ element, type, callback, options });\n    }\n\n    element[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options);\n  });\n}\n\n// Bind event handler\nexport function on(element, events = '', callback, passive = true, capture = false) {\n  toggleListener.call(this, element, events, callback, true, passive, capture);\n}\n\n// Unbind event handler\nexport function off(element, events = '', callback, passive = true, capture = false) {\n  toggleListener.call(this, element, events, callback, false, passive, capture);\n}\n\n// Bind once-only event handler\nexport function once(element, events = '', callback, passive = true, capture = false) {\n  const onceCallback = (...args) => {\n    off(element, events, onceCallback, passive, capture);\n    callback.apply(this, args);\n  };\n\n  toggleListener.call(this, element, events, onceCallback, true, passive, capture);\n}\n\n// Trigger event\nexport function triggerEvent(element, type = '', bubbles = false, detail = {}) {\n  // Bail if no element\n  if (!is.element(element) || is.empty(type)) {\n    return;\n  }\n\n  // Create and dispatch the event\n  const event = new CustomEvent(type, {\n    bubbles,\n    detail: { ...detail, plyr: this },\n  });\n\n  // Dispatch the event\n  element.dispatchEvent(event);\n}\n\n// Unbind all cached event listeners\nexport function unbindListeners() {\n  if (this && this.eventListeners) {\n    this.eventListeners.forEach((item) => {\n      const { element, type, callback, options } = item;\n      element.removeEventListener(type, callback, options);\n    });\n\n    this.eventListeners = [];\n  }\n}\n\n// Run method when / if player is ready\nexport function ready() {\n  return new Promise((resolve) =>\n    this.ready ? setTimeout(resolve, 0) : on.call(this, this.elements.container, 'ready', resolve),\n  ).then(() => {});\n}\n", "import is from './is';\n/**\n * Silence a Promise-like object.\n * This is useful for avoiding non-harmful, but potentially confusing \"uncaught\n * play promise\" rejection error messages.\n * @param  {Object} value An object that may or may not be `Promise`-like.\n */\nexport function silencePromise(value) {\n  if (is.promise(value)) {\n    value.then(null, () => {});\n  }\n}\n\nexport default { silencePromise };\n", "// ==========================================================================\n// Array utils\n// ==========================================================================\n\nimport is from './is';\n\n// Remove duplicates in an array\nexport function dedupe(array) {\n  if (!is.array(array)) {\n    return array;\n  }\n\n  return array.filter((item, index) => array.indexOf(item) === index);\n}\n\n// Get the closest value in an array\nexport function closest(array, value) {\n  if (!is.array(array) || !array.length) {\n    return null;\n  }\n\n  return array.reduce((prev, curr) => (Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev));\n}\n", "// ==========================================================================\n// Style utils\n// ==========================================================================\n\nimport { closest } from './arrays';\nimport is from './is';\n\n// Check support for a CSS declaration\nexport function supportsCSS(declaration) {\n  if (!window || !window.CSS) {\n    return false;\n  }\n\n  return window.CSS.supports(declaration);\n}\n\n// Standard/common aspect ratios\nconst standardRatios = [\n  [1, 1],\n  [4, 3],\n  [3, 4],\n  [5, 4],\n  [4, 5],\n  [3, 2],\n  [2, 3],\n  [16, 10],\n  [10, 16],\n  [16, 9],\n  [9, 16],\n  [21, 9],\n  [9, 21],\n  [32, 9],\n  [9, 32],\n].reduce((out, [x, y]) => ({ ...out, [x / y]: [x, y] }), {});\n\n// Validate an aspect ratio\nexport function validateAspectRatio(input) {\n  if (!is.array(input) && (!is.string(input) || !input.includes(':'))) {\n    return false;\n  }\n\n  const ratio = is.array(input) ? input : input.split(':');\n\n  return ratio.map(Number).every(is.number);\n}\n\n// Reduce an aspect ratio to it's lowest form\nexport function reduceAspectRatio(ratio) {\n  if (!is.array(ratio) || !ratio.every(is.number)) {\n    return null;\n  }\n\n  const [width, height] = ratio;\n  const getDivider = (w, h) => (h === 0 ? w : getDivider(h, w % h));\n  const divider = getDivider(width, height);\n\n  return [width / divider, height / divider];\n}\n\n// Calculate an aspect ratio\nexport function getAspectRatio(input) {\n  const parse = (ratio) => (validateAspectRatio(ratio) ? ratio.split(':').map(Number) : null);\n  // Try provided ratio\n  let ratio = parse(input);\n\n  // Get from config\n  if (ratio === null) {\n    ratio = parse(this.config.ratio);\n  }\n\n  // Get from embed\n  if (ratio === null && !is.empty(this.embed) && is.array(this.embed.ratio)) {\n    ({ ratio } = this.embed);\n  }\n\n  // Get from HTML5 video\n  if (ratio === null && this.isHTML5) {\n    const { videoWidth, videoHeight } = this.media;\n    ratio = [videoWidth, videoHeight];\n  }\n\n  return reduceAspectRatio(ratio);\n}\n\n// Set aspect ratio for responsive container\nexport function setAspectRatio(input) {\n  if (!this.isVideo) {\n    return {};\n  }\n\n  const { wrapper } = this.elements;\n  const ratio = getAspectRatio.call(this, input);\n\n  if (!is.array(ratio)) {\n    return {};\n  }\n\n  const [x, y] = reduceAspectRatio(ratio);\n  const useNative = supportsCSS(`aspect-ratio: ${x}/${y}`);\n  const padding = (100 / x) * y;\n\n  if (useNative) {\n    wrapper.style.aspectRatio = `${x}/${y}`;\n  } else {\n    wrapper.style.paddingBottom = `${padding}%`;\n  }\n\n  // For Vimeo we have an extra <div> to hide the standard controls and UI\n  if (this.isVimeo && !this.config.vimeo.premium && this.supported.ui) {\n    const height = (100 / this.media.offsetWidth) * parseInt(window.getComputedStyle(this.media).paddingBottom, 10);\n    const offset = (height - padding) / (height / 50);\n\n    if (this.fullscreen.active) {\n      wrapper.style.paddingBottom = null;\n    } else {\n      this.media.style.transform = `translateY(-${offset}%)`;\n    }\n  } else if (this.isHTML5) {\n    wrapper.classList.add(this.config.classNames.videoFixedRatio);\n  }\n\n  return { padding, ratio };\n}\n\n// Round an aspect ratio to closest standard ratio\nexport function roundAspectRatio(x, y, tolerance = 0.05) {\n  const ratio = x / y;\n  const closestRatio = closest(Object.keys(standardRatios), ratio);\n\n  // Check match is within tolerance\n  if (Math.abs(closestRatio - ratio) <= tolerance) {\n    return standardRatios[closestRatio];\n  }\n\n  // No match\n  return [x, y];\n}\n\n// Get the size of the viewport\n// https://stackoverflow.com/questions/1248081/how-to-get-the-browser-viewport-dimensions\nexport function getViewportSize() {\n  const width = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);\n  const height = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0);\n  return [width, height];\n}\n", "// ==========================================================================\n// Plyr HTML5 helpers\n// ==========================================================================\n\nimport support from './support';\nimport { removeElement } from './utils/elements';\nimport { triggerEvent } from './utils/events';\nimport is from './utils/is';\nimport { silencePromise } from './utils/promise';\nimport { setAspectRatio } from './utils/style';\n\nconst html5 = {\n  getSources() {\n    if (!this.isHTML5) {\n      return [];\n    }\n\n    const sources = Array.from(this.media.querySelectorAll('source'));\n\n    // Filter out unsupported sources (if type is specified)\n    return sources.filter((source) => {\n      const type = source.getAttribute('type');\n\n      if (is.empty(type)) {\n        return true;\n      }\n\n      return support.mime.call(this, type);\n    });\n  },\n\n  // Get quality levels\n  getQualityOptions() {\n    // Whether we're forcing all options (e.g. for streaming)\n    if (this.config.quality.forced) {\n      return this.config.quality.options;\n    }\n\n    // Get sizes from <source> elements\n    return html5.getSources\n      .call(this)\n      .map((source) => Number(source.getAttribute('size')))\n      .filter(Boolean);\n  },\n\n  setup() {\n    if (!this.isHTML5) {\n      return;\n    }\n\n    const player = this;\n\n    // Set speed options from config\n    player.options.speed = player.config.speed.options;\n\n    // Set aspect ratio if fixed\n    if (!is.empty(this.config.ratio)) {\n      setAspectRatio.call(player);\n    }\n\n    // Quality\n    Object.defineProperty(player.media, 'quality', {\n      get() {\n        // Get sources\n        const sources = html5.getSources.call(player);\n        const source = sources.find((s) => s.getAttribute('src') === player.source);\n\n        // Return size, if match is found\n        return source && Number(source.getAttribute('size'));\n      },\n      set(input) {\n        if (player.quality === input) {\n          return;\n        }\n\n        // If we're using an external handler...\n        if (player.config.quality.forced && is.function(player.config.quality.onChange)) {\n          player.config.quality.onChange(input);\n        } else {\n          // Get sources\n          const sources = html5.getSources.call(player);\n          // Get first match for requested size\n          const source = sources.find((s) => Number(s.getAttribute('size')) === input);\n\n          // No matching source found\n          if (!source) {\n            return;\n          }\n\n          // Get current state\n          const { currentTime, paused, preload, readyState, playbackRate } = player.media;\n\n          // Set new source\n          player.media.src = source.getAttribute('src');\n\n          // Prevent loading if preload=\"none\" and the current source isn't loaded (#1044)\n          if (preload !== 'none' || readyState) {\n            // Restore time\n            player.once('loadedmetadata', () => {\n              player.speed = playbackRate;\n              player.currentTime = currentTime;\n\n              // Resume playing\n              if (!paused) {\n                silencePromise(player.play());\n              }\n            });\n\n            // Load new source\n            player.media.load();\n          }\n        }\n\n        // Trigger change event\n        triggerEvent.call(player, player.media, 'qualitychange', false, {\n          quality: input,\n        });\n      },\n    });\n  },\n\n  // Cancel current network requests\n  // See https://github.com/sampotts/plyr/issues/174\n  cancelRequests() {\n    if (!this.isHTML5) {\n      return;\n    }\n\n    // Remove child sources\n    removeElement(html5.getSources.call(this));\n\n    // Set blank video src attribute\n    // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error\n    // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection\n    this.media.setAttribute('src', this.config.blankVideo);\n\n    // Load the new empty source\n    // This will cancel existing requests\n    // See https://github.com/sampotts/plyr/issues/174\n    this.media.load();\n\n    // Debugging\n    this.debug.log('Cancelled network requests');\n  },\n};\n\nexport default html5;\n", "// ==========================================================================\n// String utils\n// ==========================================================================\n\nimport is from './is';\n\n// Generate a random ID\nexport function generateId(prefix) {\n  return `${prefix}-${Math.floor(Math.random() * 10000)}`;\n}\n\n// Format string\nexport function format(input, ...args) {\n  if (is.empty(input)) {\n    return input;\n  }\n\n  return input.toString().replace(/{(\\d+)}/g, (match, i) => args[i].toString());\n}\n\n// Get percentage\nexport function getPercentage(current, max) {\n  if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) {\n    return 0;\n  }\n\n  return ((current / max) * 100).toFixed(2);\n}\n\n// Replace all occurances of a string in a string\nexport const replaceAll = (input = '', find = '', replace = '') =>\n  input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\\]/\\\\])/g, '\\\\$1'), 'g'), replace.toString());\n\n// Convert to title case\nexport const toTitleCase = (input = '') =>\n  input.toString().replace(/\\w\\S*/g, (text) => text.charAt(0).toUpperCase() + text.substr(1).toLowerCase());\n\n// Convert string to pascalCase\nexport function toPascalCase(input = '') {\n  let string = input.toString();\n\n  // Convert kebab case\n  string = replaceAll(string, '-', ' ');\n\n  // Convert snake case\n  string = replaceAll(string, '_', ' ');\n\n  // Convert to title case\n  string = toTitleCase(string);\n\n  // Convert to pascal case\n  return replaceAll(string, ' ', '');\n}\n\n// Convert string to pascalCase\nexport function toCamelCase(input = '') {\n  let string = input.toString();\n\n  // Convert to pascal case\n  string = toPascalCase(string);\n\n  // Convert first character to lowercase\n  return string.charAt(0).toLowerCase() + string.slice(1);\n}\n\n// Remove HTML from a string\nexport function stripHTML(source) {\n  const fragment = document.createDocumentFragment();\n  const element = document.createElement('div');\n  fragment.appendChild(element);\n  element.innerHTML = source;\n  return fragment.firstChild.innerText;\n}\n\n// Like outerHTML, but also works for DocumentFragment\nexport function getHTML(element) {\n  const wrapper = document.createElement('div');\n  wrapper.appendChild(element);\n  return wrapper.innerHTML;\n}\n", "// ==========================================================================\n// Plyr internationalization\n// ==========================================================================\n\nimport is from './is';\nimport { getDeep } from './objects';\nimport { replaceAll } from './strings';\n\n// Skip i18n for abbreviations and brand names\nconst resources = {\n  pip: 'PIP',\n  airplay: 'AirPlay',\n  html5: 'HTML5',\n  vimeo: 'Vimeo',\n  youtube: 'YouTube',\n};\n\nconst i18n = {\n  get(key = '', config = {}) {\n    if (is.empty(key) || is.empty(config)) {\n      return '';\n    }\n\n    let string = getDeep(config.i18n, key);\n\n    if (is.empty(string)) {\n      if (Object.keys(resources).includes(key)) {\n        return resources[key];\n      }\n\n      return '';\n    }\n\n    const replace = {\n      '{seektime}': config.seekTime,\n      '{title}': config.title,\n    };\n\n    Object.entries(replace).forEach(([k, v]) => {\n      string = replaceAll(string, k, v);\n    });\n\n    return string;\n  },\n};\n\nexport default i18n;\n", "// ==========================================================================\n// Plyr storage\n// ==========================================================================\n\nimport is from './utils/is';\nimport { extend } from './utils/objects';\n\nclass Storage {\n  constructor(player) {\n    this.enabled = player.config.storage.enabled;\n    this.key = player.config.storage.key;\n  }\n\n  // Check for actual support (see if we can use it)\n  static get supported() {\n    try {\n      if (!('localStorage' in window)) {\n        return false;\n      }\n\n      const test = '___test';\n\n      // Try to use it (it might be disabled, e.g. user is in private mode)\n      // see: https://github.com/sampotts/plyr/issues/131\n      window.localStorage.setItem(test, test);\n      window.localStorage.removeItem(test);\n\n      return true;\n    } catch (_) {\n      return false;\n    }\n  }\n\n  get = (key) => {\n    if (!Storage.supported || !this.enabled) {\n      return null;\n    }\n\n    const store = window.localStorage.getItem(this.key);\n\n    if (is.empty(store)) {\n      return null;\n    }\n\n    const json = JSON.parse(store);\n\n    return is.string(key) && key.length ? json[key] : json;\n  };\n\n  set = (object) => {\n    // Bail if we don't have localStorage support or it's disabled\n    if (!Storage.supported || !this.enabled) {\n      return;\n    }\n\n    // Can only store objectst\n    if (!is.object(object)) {\n      return;\n    }\n\n    // Get current storage\n    let storage = this.get();\n\n    // Default to empty object\n    if (is.empty(storage)) {\n      storage = {};\n    }\n\n    // Update the working copy of the values\n    extend(storage, object);\n\n    // Update storage\n    try {\n      window.localStorage.setItem(this.key, JSON.stringify(storage));\n    } catch (_) {\n      // Do nothing\n    }\n  };\n}\n\nexport default Storage;\n", "// ==========================================================================\n// Fetch wrapper\n// Using XHR to avoid issues with older browsers\n// ==========================================================================\n\nexport default function fetch(url, responseType = 'text') {\n  return new Promise((resolve, reject) => {\n    try {\n      const request = new XMLHttpRequest();\n\n      // Check for CORS support\n      if (!('withCredentials' in request)) {\n        return;\n      }\n\n      request.addEventListener('load', () => {\n        if (responseType === 'text') {\n          try {\n            resolve(JSON.parse(request.responseText));\n          } catch (_) {\n            resolve(request.responseText);\n          }\n        } else {\n          resolve(request.response);\n        }\n      });\n\n      request.addEventListener('error', () => {\n        throw new Error(request.status);\n      });\n\n      request.open('GET', url, true);\n\n      // Set the required response type\n      request.responseType = responseType;\n\n      request.send();\n    } catch (error) {\n      reject(error);\n    }\n  });\n}\n", "// ==========================================================================\n// Sprite loader\n// ==========================================================================\n\nimport Storage from '../storage';\nimport fetch from './fetch';\nimport is from './is';\n\n// Load an external SVG sprite\nexport default function loadSprite(url, id) {\n  if (!is.string(url)) {\n    return;\n  }\n\n  const prefix = 'cache';\n  const hasId = is.string(id);\n  let isCached = false;\n  const exists = () => document.getElementById(id) !== null;\n\n  const update = (container, data) => {\n    // eslint-disable-next-line no-param-reassign\n    container.innerHTML = data;\n\n    // Check again incase of race condition\n    if (hasId && exists()) {\n      return;\n    }\n\n    // Inject the SVG to the body\n    document.body.insertAdjacentElement('afterbegin', container);\n  };\n\n  // Only load once if ID set\n  if (!hasId || !exists()) {\n    const useStorage = Storage.supported;\n    // Create container\n    const container = document.createElement('div');\n    container.setAttribute('hidden', '');\n\n    if (hasId) {\n      container.setAttribute('id', id);\n    }\n\n    // Check in cache\n    if (useStorage) {\n      const cached = window.localStorage.getItem(`${prefix}-${id}`);\n      isCached = cached !== null;\n\n      if (isCached) {\n        const data = JSON.parse(cached);\n        update(container, data.content);\n      }\n    }\n\n    // Get the sprite\n    fetch(url)\n      .then((result) => {\n        if (is.empty(result)) {\n          return;\n        }\n\n        if (useStorage) {\n          try {\n            window.localStorage.setItem(\n              `${prefix}-${id}`,\n              JSON.stringify({\n                content: result,\n              }),\n            );\n          } catch (_) {\n            // Do nothing\n          }\n        }\n\n        update(container, result);\n      })\n      .catch(() => {});\n  }\n}\n", "// ==========================================================================\n// Time utils\n// ==========================================================================\n\nimport is from './is';\n\n// Time helpers\nexport const getHours = (value) => Math.trunc((value / 60 / 60) % 60, 10);\nexport const getMinutes = (value) => Math.trunc((value / 60) % 60, 10);\nexport const getSeconds = (value) => Math.trunc(value % 60, 10);\n\n// Format time to UI friendly string\nexport function formatTime(time = 0, displayHours = false, inverted = false) {\n  // Bail if the value isn't a number\n  if (!is.number(time)) {\n    return formatTime(undefined, displayHours, inverted);\n  }\n\n  // Format time component to add leading zero\n  const format = (value) => `0${value}`.slice(-2);\n  // Breakdown to hours, mins, secs\n  let hours = getHours(time);\n  const mins = getMinutes(time);\n  const secs = getSeconds(time);\n\n  // Do we need to display hours?\n  if (displayHours || hours > 0) {\n    hours = `${hours}:`;\n  } else {\n    hours = '';\n  }\n\n  // Render\n  return `${inverted && time > 0 ? '-' : ''}${hours}${format(mins)}:${format(secs)}`;\n}\n", "// ==========================================================================\n// Plyr controls\n// TODO: This needs to be split into smaller files and cleaned up\n// ==========================================================================\n\nimport RangeTouch from 'rangetouch';\n\nimport captions from './captions';\nimport html5 from './html5';\nimport support from './support';\nimport { repaint, transitionEndEvent } from './utils/animation';\nimport { dedupe } from './utils/arrays';\nimport browser from './utils/browser';\nimport {\n  createElement,\n  emptyElement,\n  getAttributesFromSelector,\n  getElement,\n  getElements,\n  hasClass,\n  matches,\n  removeElement,\n  setAttributes,\n  setFocus,\n  toggleClass,\n  toggleHidden,\n} from './utils/elements';\nimport { off, on } from './utils/events';\nimport i18n from './utils/i18n';\nimport is from './utils/is';\nimport loadSprite from './utils/load-sprite';\nimport { extend } from './utils/objects';\nimport { getPercentage, replaceAll, toCamelCase, toTitleCase } from './utils/strings';\nimport { formatTime, getHours } from './utils/time';\n\n// TODO: Don't export a massive object - break down and create class\nconst controls = {\n  // Get icon URL\n  getIconUrl() {\n    const url = new URL(this.config.iconUrl, window.location);\n    const host = window.location.host ? window.location.host : window.top.location.host;\n    const cors = url.host !== host || (browser.isIE && !window.svg4everybody);\n\n    return {\n      url: this.config.iconUrl,\n      cors,\n    };\n  },\n\n  // Find the UI controls\n  findElements() {\n    try {\n      this.elements.controls = getElement.call(this, this.config.selectors.controls.wrapper);\n\n      // Buttons\n      this.elements.buttons = {\n        play: getElements.call(this, this.config.selectors.buttons.play),\n        pause: getElement.call(this, this.config.selectors.buttons.pause),\n        restart: getElement.call(this, this.config.selectors.buttons.restart),\n        rewind: getElement.call(this, this.config.selectors.buttons.rewind),\n        fastForward: getElement.call(this, this.config.selectors.buttons.fastForward),\n        mute: getElement.call(this, this.config.selectors.buttons.mute),\n        pip: getElement.call(this, this.config.selectors.buttons.pip),\n        airplay: getElement.call(this, this.config.selectors.buttons.airplay),\n        settings: getElement.call(this, this.config.selectors.buttons.settings),\n        captions: getElement.call(this, this.config.selectors.buttons.captions),\n        fullscreen: getElement.call(this, this.config.selectors.buttons.fullscreen),\n      };\n\n      // Progress\n      this.elements.progress = getElement.call(this, this.config.selectors.progress);\n\n      // Inputs\n      this.elements.inputs = {\n        seek: getElement.call(this, this.config.selectors.inputs.seek),\n        volume: getElement.call(this, this.config.selectors.inputs.volume),\n      };\n\n      // Display\n      this.elements.display = {\n        buffer: getElement.call(this, this.config.selectors.display.buffer),\n        currentTime: getElement.call(this, this.config.selectors.display.currentTime),\n        duration: getElement.call(this, this.config.selectors.display.duration),\n      };\n\n      // Seek tooltip\n      if (is.element(this.elements.progress)) {\n        this.elements.display.seekTooltip = this.elements.progress.querySelector(`.${this.config.classNames.tooltip}`);\n      }\n\n      return true;\n    } catch (error) {\n      // Log it\n      this.debug.warn('It looks like there is a problem with your custom controls HTML', error);\n\n      // Restore native video controls\n      this.toggleNativeControls(true);\n\n      return false;\n    }\n  },\n\n  // Create <svg> icon\n  createIcon(type, attributes) {\n    const namespace = 'http://www.w3.org/2000/svg';\n    const iconUrl = controls.getIconUrl.call(this);\n    const iconPath = `${!iconUrl.cors ? iconUrl.url : ''}#${this.config.iconPrefix}`;\n    // Create <svg>\n    const icon = document.createElementNS(namespace, 'svg');\n    setAttributes(\n      icon,\n      extend(attributes, {\n        'aria-hidden': 'true',\n        focusable: 'false',\n      }),\n    );\n\n    // Create the <use> to reference sprite\n    const use = document.createElementNS(namespace, 'use');\n    const path = `${iconPath}-${type}`;\n\n    // Set `href` attributes\n    // https://github.com/sampotts/plyr/issues/460\n    // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href\n    if ('href' in use) {\n      use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path);\n    }\n\n    // Always set the older attribute even though it's \"deprecated\" (it'll be around for ages)\n    use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path);\n\n    // Add <use> to <svg>\n    icon.appendChild(use);\n\n    return icon;\n  },\n\n  // Create hidden text label\n  createLabel(key, attr = {}) {\n    const text = i18n.get(key, this.config);\n    const attributes = { ...attr, class: [attr.class, this.config.classNames.hidden].filter(Boolean).join(' ') };\n\n    return createElement('span', attributes, text);\n  },\n\n  // Create a badge\n  createBadge(text) {\n    if (is.empty(text)) {\n      return null;\n    }\n\n    const badge = createElement('span', {\n      class: this.config.classNames.menu.value,\n    });\n\n    badge.appendChild(\n      createElement(\n        'span',\n        {\n          class: this.config.classNames.menu.badge,\n        },\n        text,\n      ),\n    );\n\n    return badge;\n  },\n\n  // Create a <button>\n  createButton(buttonType, attr) {\n    const attributes = extend({}, attr);\n    let type = toCamelCase(buttonType);\n\n    const props = {\n      element: 'button',\n      toggle: false,\n      label: null,\n      icon: null,\n      labelPressed: null,\n      iconPressed: null,\n    };\n\n    ['element', 'icon', 'label'].forEach((key) => {\n      if (Object.keys(attributes).includes(key)) {\n        props[key] = attributes[key];\n        delete attributes[key];\n      }\n    });\n\n    // Default to 'button' type to prevent form submission\n    if (props.element === 'button' && !Object.keys(attributes).includes('type')) {\n      attributes.type = 'button';\n    }\n\n    // Set class name\n    if (Object.keys(attributes).includes('class')) {\n      if (!attributes.class.split(' ').some((c) => c === this.config.classNames.control)) {\n        extend(attributes, {\n          class: `${attributes.class} ${this.config.classNames.control}`,\n        });\n      }\n    } else {\n      attributes.class = this.config.classNames.control;\n    }\n\n    // Large play button\n    switch (buttonType) {\n      case 'play':\n        props.toggle = true;\n        props.label = 'play';\n        props.labelPressed = 'pause';\n        props.icon = 'play';\n        props.iconPressed = 'pause';\n        break;\n\n      case 'mute':\n        props.toggle = true;\n        props.label = 'mute';\n        props.labelPressed = 'unmute';\n        props.icon = 'volume';\n        props.iconPressed = 'muted';\n        break;\n\n      case 'captions':\n        props.toggle = true;\n        props.label = 'enableCaptions';\n        props.labelPressed = 'disableCaptions';\n        props.icon = 'captions-off';\n        props.iconPressed = 'captions-on';\n        break;\n\n      case 'fullscreen':\n        props.toggle = true;\n        props.label = 'enterFullscreen';\n        props.labelPressed = 'exitFullscreen';\n        props.icon = 'enter-fullscreen';\n        props.iconPressed = 'exit-fullscreen';\n        break;\n\n      case 'play-large':\n        attributes.class += ` ${this.config.classNames.control}--overlaid`;\n        type = 'play';\n        props.label = 'play';\n        props.icon = 'play';\n        break;\n\n      default:\n        if (is.empty(props.label)) {\n          props.label = type;\n        }\n        if (is.empty(props.icon)) {\n          props.icon = buttonType;\n        }\n    }\n\n    const button = createElement(props.element);\n\n    // Setup toggle icon and labels\n    if (props.toggle) {\n      // Icon\n      button.appendChild(\n        controls.createIcon.call(this, props.iconPressed, {\n          class: 'icon--pressed',\n        }),\n      );\n      button.appendChild(\n        controls.createIcon.call(this, props.icon, {\n          class: 'icon--not-pressed',\n        }),\n      );\n\n      // Label/Tooltip\n      button.appendChild(\n        controls.createLabel.call(this, props.labelPressed, {\n          class: 'label--pressed',\n        }),\n      );\n      button.appendChild(\n        controls.createLabel.call(this, props.label, {\n          class: 'label--not-pressed',\n        }),\n      );\n    } else {\n      button.appendChild(controls.createIcon.call(this, props.icon));\n      button.appendChild(controls.createLabel.call(this, props.label));\n    }\n\n    // Merge and set attributes\n    extend(attributes, getAttributesFromSelector(this.config.selectors.buttons[type], attributes));\n    setAttributes(button, attributes);\n\n    // We have multiple play buttons\n    if (type === 'play') {\n      if (!is.array(this.elements.buttons[type])) {\n        this.elements.buttons[type] = [];\n      }\n\n      this.elements.buttons[type].push(button);\n    } else {\n      this.elements.buttons[type] = button;\n    }\n\n    return button;\n  },\n\n  // Create an <input type='range'>\n  createRange(type, attributes) {\n    // Seek input\n    const input = createElement(\n      'input',\n      extend(\n        getAttributesFromSelector(this.config.selectors.inputs[type]),\n        {\n          type: 'range',\n          min: 0,\n          max: 100,\n          step: 0.01,\n          value: 0,\n          autocomplete: 'off',\n          // A11y fixes for https://github.com/sampotts/plyr/issues/905\n          role: 'slider',\n          'aria-label': i18n.get(type, this.config),\n          'aria-valuemin': 0,\n          'aria-valuemax': 100,\n          'aria-valuenow': 0,\n        },\n        attributes,\n      ),\n    );\n\n    this.elements.inputs[type] = input;\n\n    // Set the fill for webkit now\n    controls.updateRangeFill.call(this, input);\n\n    // Improve support on touch devices\n    RangeTouch.setup(input);\n\n    return input;\n  },\n\n  // Create a <progress>\n  createProgress(type, attributes) {\n    const progress = createElement(\n      'progress',\n      extend(\n        getAttributesFromSelector(this.config.selectors.display[type]),\n        {\n          min: 0,\n          max: 100,\n          value: 0,\n          role: 'progressbar',\n          'aria-hidden': true,\n        },\n        attributes,\n      ),\n    );\n\n    // Create the label inside\n    if (type !== 'volume') {\n      progress.appendChild(createElement('span', null, '0'));\n\n      const suffixKey = {\n        played: 'played',\n        buffer: 'buffered',\n      }[type];\n      const suffix = suffixKey ? i18n.get(suffixKey, this.config) : '';\n\n      progress.innerText = `% ${suffix.toLowerCase()}`;\n    }\n\n    this.elements.display[type] = progress;\n\n    return progress;\n  },\n\n  // Create time display\n  createTime(type, attrs) {\n    const attributes = getAttributesFromSelector(this.config.selectors.display[type], attrs);\n\n    const container = createElement(\n      'div',\n      extend(attributes, {\n        class: `${attributes.class ? attributes.class : ''} ${this.config.classNames.display.time} `.trim(),\n        'aria-label': i18n.get(type, this.config),\n      }),\n      '00:00',\n    );\n\n    // Reference for updates\n    this.elements.display[type] = container;\n\n    return container;\n  },\n\n  // Bind keyboard shortcuts for a menu item\n  // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus\n  // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143\n  bindMenuItemShortcuts(menuItem, type) {\n    // Navigate through menus via arrow keys and space\n    on.call(\n      this,\n      menuItem,\n      'keydown keyup',\n      (event) => {\n        // We only care about space and \u2B06\uFE0F \u2B07\uFE0F\uFE0F \u27A1\uFE0F\n        if (![32, 38, 39, 40].includes(event.which)) {\n          return;\n        }\n\n        // Prevent play / seek\n        event.preventDefault();\n        event.stopPropagation();\n\n        // We're just here to prevent the keydown bubbling\n        if (event.type === 'keydown') {\n          return;\n        }\n\n        const isRadioButton = matches(menuItem, '[role=\"menuitemradio\"]');\n\n        // Show the respective menu\n        if (!isRadioButton && [32, 39].includes(event.which)) {\n          controls.showMenuPanel.call(this, type, true);\n        } else {\n          let target;\n\n          if (event.which !== 32) {\n            if (event.which === 40 || (isRadioButton && event.which === 39)) {\n              target = menuItem.nextElementSibling;\n\n              if (!is.element(target)) {\n                target = menuItem.parentNode.firstElementChild;\n              }\n            } else {\n              target = menuItem.previousElementSibling;\n\n              if (!is.element(target)) {\n                target = menuItem.parentNode.lastElementChild;\n              }\n            }\n\n            setFocus.call(this, target, true);\n          }\n        }\n      },\n      false,\n    );\n\n    // Enter will fire a `click` event but we still need to manage focus\n    // So we bind to keyup which fires after and set focus here\n    on.call(this, menuItem, 'keyup', (event) => {\n      if (event.which !== 13) {\n        return;\n      }\n\n      controls.focusFirstMenuItem.call(this, null, true);\n    });\n  },\n\n  // Create a settings menu item\n  createMenuItem({ value, list, type, title, badge = null, checked = false }) {\n    const attributes = getAttributesFromSelector(this.config.selectors.inputs[type]);\n\n    const menuItem = createElement(\n      'button',\n      extend(attributes, {\n        type: 'button',\n        role: 'menuitemradio',\n        class: `${this.config.classNames.control} ${attributes.class ? attributes.class : ''}`.trim(),\n        'aria-checked': checked,\n        value,\n      }),\n    );\n\n    const flex = createElement('span');\n\n    // We have to set as HTML incase of special characters\n    flex.innerHTML = title;\n\n    if (is.element(badge)) {\n      flex.appendChild(badge);\n    }\n\n    menuItem.appendChild(flex);\n\n    // Replicate radio button behaviour\n    Object.defineProperty(menuItem, 'checked', {\n      enumerable: true,\n      get() {\n        return menuItem.getAttribute('aria-checked') === 'true';\n      },\n      set(check) {\n        // Ensure exclusivity\n        if (check) {\n          Array.from(menuItem.parentNode.children)\n            .filter((node) => matches(node, '[role=\"menuitemradio\"]'))\n            .forEach((node) => node.setAttribute('aria-checked', 'false'));\n        }\n\n        menuItem.setAttribute('aria-checked', check ? 'true' : 'false');\n      },\n    });\n\n    this.listeners.bind(\n      menuItem,\n      'click keyup',\n      (event) => {\n        if (is.keyboardEvent(event) && event.which !== 32) {\n          return;\n        }\n\n        event.preventDefault();\n        event.stopPropagation();\n\n        menuItem.checked = true;\n\n        switch (type) {\n          case 'language':\n            this.currentTrack = Number(value);\n            break;\n\n          case 'quality':\n            this.quality = value;\n            break;\n\n          case 'speed':\n            this.speed = parseFloat(value);\n            break;\n\n          default:\n            break;\n        }\n\n        controls.showMenuPanel.call(this, 'home', is.keyboardEvent(event));\n      },\n      type,\n      false,\n    );\n\n    controls.bindMenuItemShortcuts.call(this, menuItem, type);\n\n    list.appendChild(menuItem);\n  },\n\n  // Format a time for display\n  formatTime(time = 0, inverted = false) {\n    // Bail if the value isn't a number\n    if (!is.number(time)) {\n      return time;\n    }\n\n    // Always display hours if duration is over an hour\n    const forceHours = getHours(this.duration) > 0;\n\n    return formatTime(time, forceHours, inverted);\n  },\n\n  // Update the displayed time\n  updateTimeDisplay(target = null, time = 0, inverted = false) {\n    // Bail if there's no element to display or the value isn't a number\n    if (!is.element(target) || !is.number(time)) {\n      return;\n    }\n\n    // eslint-disable-next-line no-param-reassign\n    target.innerText = controls.formatTime(time, inverted);\n  },\n\n  // Update volume UI and storage\n  updateVolume() {\n    if (!this.supported.ui) {\n      return;\n    }\n\n    // Update range\n    if (is.element(this.elements.inputs.volume)) {\n      controls.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume);\n    }\n\n    // Update mute state\n    if (is.element(this.elements.buttons.mute)) {\n      this.elements.buttons.mute.pressed = this.muted || this.volume === 0;\n    }\n  },\n\n  // Update seek value and lower fill\n  setRange(target, value = 0) {\n    if (!is.element(target)) {\n      return;\n    }\n\n    // eslint-disable-next-line\n    target.value = value;\n\n    // Webkit range fill\n    controls.updateRangeFill.call(this, target);\n  },\n\n  // Update <progress> elements\n  updateProgress(event) {\n    if (!this.supported.ui || !is.event(event)) {\n      return;\n    }\n\n    let value = 0;\n\n    const setProgress = (target, input) => {\n      const val = is.number(input) ? input : 0;\n      const progress = is.element(target) ? target : this.elements.display.buffer;\n\n      // Update value and label\n      if (is.element(progress)) {\n        progress.value = val;\n\n        // Update text label inside\n        const label = progress.getElementsByTagName('span')[0];\n        if (is.element(label)) {\n          label.childNodes[0].nodeValue = val;\n        }\n      }\n    };\n\n    if (event) {\n      switch (event.type) {\n        // Video playing\n        case 'timeupdate':\n        case 'seeking':\n        case 'seeked':\n          value = getPercentage(this.currentTime, this.duration);\n\n          // Set seek range value only if it's a 'natural' time event\n          if (event.type === 'timeupdate') {\n            controls.setRange.call(this, this.elements.inputs.seek, value);\n          }\n\n          break;\n\n        // Check buffer status\n        case 'playing':\n        case 'progress':\n          setProgress(this.elements.display.buffer, this.buffered * 100);\n\n          break;\n\n        default:\n          break;\n      }\n    }\n  },\n\n  // Webkit polyfill for lower fill range\n  updateRangeFill(target) {\n    // Get range from event if event passed\n    const range = is.event(target) ? target.target : target;\n\n    // Needs to be a valid <input type='range'>\n    if (!is.element(range) || range.getAttribute('type') !== 'range') {\n      return;\n    }\n\n    // Set aria values for https://github.com/sampotts/plyr/issues/905\n    if (matches(range, this.config.selectors.inputs.seek)) {\n      range.setAttribute('aria-valuenow', this.currentTime);\n      const currentTime = controls.formatTime(this.currentTime);\n      const duration = controls.formatTime(this.duration);\n      const format = i18n.get('seekLabel', this.config);\n      range.setAttribute(\n        'aria-valuetext',\n        format.replace('{currentTime}', currentTime).replace('{duration}', duration),\n      );\n    } else if (matches(range, this.config.selectors.inputs.volume)) {\n      const percent = range.value * 100;\n      range.setAttribute('aria-valuenow', percent);\n      range.setAttribute('aria-valuetext', `${percent.toFixed(1)}%`);\n    } else {\n      range.setAttribute('aria-valuenow', range.value);\n    }\n\n    // WebKit only\n    if (!browser.isWebkit) {\n      return;\n    }\n\n    // Set CSS custom property\n    range.style.setProperty('--value', `${(range.value / range.max) * 100}%`);\n  },\n\n  // Update hover tooltip for seeking\n  updateSeekTooltip(event) {\n    // Bail if setting not true\n    if (\n      !this.config.tooltips.seek ||\n      !is.element(this.elements.inputs.seek) ||\n      !is.element(this.elements.display.seekTooltip) ||\n      this.duration === 0\n    ) {\n      return;\n    }\n\n    const visible = `${this.config.classNames.tooltip}--visible`;\n    const toggle = (show) => toggleClass(this.elements.display.seekTooltip, visible, show);\n\n    // Hide on touch\n    if (this.touch) {\n      toggle(false);\n      return;\n    }\n\n    // Determine percentage, if already visible\n    let percent = 0;\n    const clientRect = this.elements.progress.getBoundingClientRect();\n\n    if (is.event(event)) {\n      percent = (100 / clientRect.width) * (event.pageX - clientRect.left);\n    } else if (hasClass(this.elements.display.seekTooltip, visible)) {\n      percent = parseFloat(this.elements.display.seekTooltip.style.left, 10);\n    } else {\n      return;\n    }\n\n    // Set bounds\n    if (percent < 0) {\n      percent = 0;\n    } else if (percent > 100) {\n      percent = 100;\n    }\n\n    // Display the time a click would seek to\n    controls.updateTimeDisplay.call(this, this.elements.display.seekTooltip, (this.duration / 100) * percent);\n\n    // Set position\n    this.elements.display.seekTooltip.style.left = `${percent}%`;\n\n    // Show/hide the tooltip\n    // If the event is a moues in/out and percentage is inside bounds\n    if (is.event(event) && ['mouseenter', 'mouseleave'].includes(event.type)) {\n      toggle(event.type === 'mouseenter');\n    }\n  },\n\n  // Handle time change event\n  timeUpdate(event) {\n    // Only invert if only one time element is displayed and used for both duration and currentTime\n    const invert = !is.element(this.elements.display.duration) && this.config.invertTime;\n\n    // Duration\n    controls.updateTimeDisplay.call(\n      this,\n      this.elements.display.currentTime,\n      invert ? this.duration - this.currentTime : this.currentTime,\n      invert,\n    );\n\n    // Ignore updates while seeking\n    if (event && event.type === 'timeupdate' && this.media.seeking) {\n      return;\n    }\n\n    // Playing progress\n    controls.updateProgress.call(this, event);\n  },\n\n  // Show the duration on metadataloaded or durationchange events\n  durationUpdate() {\n    // Bail if no UI or durationchange event triggered after playing/seek when invertTime is false\n    if (!this.supported.ui || (!this.config.invertTime && this.currentTime)) {\n      return;\n    }\n\n    // If duration is the 2**32 (shaka), Infinity (HLS), DASH-IF (Number.MAX_SAFE_INTEGER || Number.MAX_VALUE) indicating live we hide the currentTime and progressbar.\n    // https://github.com/video-dev/hls.js/blob/5820d29d3c4c8a46e8b75f1e3afa3e68c1a9a2db/src/controller/buffer-controller.js#L415\n    // https://github.com/google/shaka-player/blob/4d889054631f4e1cf0fbd80ddd2b71887c02e232/lib/media/streaming_engine.js#L1062\n    // https://github.com/Dash-Industry-Forum/dash.js/blob/69859f51b969645b234666800d4cb596d89c602d/src/dash/models/DashManifestModel.js#L338\n    if (this.duration >= 2 ** 32) {\n      toggleHidden(this.elements.display.currentTime, true);\n      toggleHidden(this.elements.progress, true);\n      return;\n    }\n\n    // Update ARIA values\n    if (is.element(this.elements.inputs.seek)) {\n      this.elements.inputs.seek.setAttribute('aria-valuemax', this.duration);\n    }\n\n    // If there's a spot to display duration\n    const hasDuration = is.element(this.elements.display.duration);\n\n    // If there's only one time display, display duration there\n    if (!hasDuration && this.config.displayDuration && this.paused) {\n      controls.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration);\n    }\n\n    // If there's a duration element, update content\n    if (hasDuration) {\n      controls.updateTimeDisplay.call(this, this.elements.display.duration, this.duration);\n    }\n\n    // Update the tooltip (if visible)\n    controls.updateSeekTooltip.call(this);\n  },\n\n  // Hide/show a tab\n  toggleMenuButton(setting, toggle) {\n    toggleHidden(this.elements.settings.buttons[setting], !toggle);\n  },\n\n  // Update the selected setting\n  updateSetting(setting, container, input) {\n    const pane = this.elements.settings.panels[setting];\n    let value = null;\n    let list = container;\n\n    if (setting === 'captions') {\n      value = this.currentTrack;\n    } else {\n      value = !is.empty(input) ? input : this[setting];\n\n      // Get default\n      if (is.empty(value)) {\n        value = this.config[setting].default;\n      }\n\n      // Unsupported value\n      if (!is.empty(this.options[setting]) && !this.options[setting].includes(value)) {\n        this.debug.warn(`Unsupported value of '${value}' for ${setting}`);\n        return;\n      }\n\n      // Disabled value\n      if (!this.config[setting].options.includes(value)) {\n        this.debug.warn(`Disabled value of '${value}' for ${setting}`);\n        return;\n      }\n    }\n\n    // Get the list if we need to\n    if (!is.element(list)) {\n      list = pane && pane.querySelector('[role=\"menu\"]');\n    }\n\n    // If there's no list it means it's not been rendered...\n    if (!is.element(list)) {\n      return;\n    }\n\n    // Update the label\n    const label = this.elements.settings.buttons[setting].querySelector(`.${this.config.classNames.menu.value}`);\n    label.innerHTML = controls.getLabel.call(this, setting, value);\n\n    // Find the radio option and check it\n    const target = list && list.querySelector(`[value=\"${value}\"]`);\n\n    if (is.element(target)) {\n      target.checked = true;\n    }\n  },\n\n  // Translate a value into a nice label\n  getLabel(setting, value) {\n    switch (setting) {\n      case 'speed':\n        return value === 1 ? i18n.get('normal', this.config) : `${value}&times;`;\n\n      case 'quality':\n        if (is.number(value)) {\n          const label = i18n.get(`qualityLabel.${value}`, this.config);\n\n          if (!label.length) {\n            return `${value}p`;\n          }\n\n          return label;\n        }\n\n        return toTitleCase(value);\n\n      case 'captions':\n        return captions.getLabel.call(this);\n\n      default:\n        return null;\n    }\n  },\n\n  // Set the quality menu\n  setQualityMenu(options) {\n    // Menu required\n    if (!is.element(this.elements.settings.panels.quality)) {\n      return;\n    }\n\n    const type = 'quality';\n    const list = this.elements.settings.panels.quality.querySelector('[role=\"menu\"]');\n\n    // Set options if passed and filter based on uniqueness and config\n    if (is.array(options)) {\n      this.options.quality = dedupe(options).filter((quality) => this.config.quality.options.includes(quality));\n    }\n\n    // Toggle the pane and tab\n    const toggle = !is.empty(this.options.quality) && this.options.quality.length > 1;\n    controls.toggleMenuButton.call(this, type, toggle);\n\n    // Empty the menu\n    emptyElement(list);\n\n    // Check if we need to toggle the parent\n    controls.checkMenu.call(this);\n\n    // If we're hiding, nothing more to do\n    if (!toggle) {\n      return;\n    }\n\n    // Get the badge HTML for HD, 4K etc\n    const getBadge = (quality) => {\n      const label = i18n.get(`qualityBadge.${quality}`, this.config);\n\n      if (!label.length) {\n        return null;\n      }\n\n      return controls.createBadge.call(this, label);\n    };\n\n    // Sort options by the config and then render options\n    this.options.quality\n      .sort((a, b) => {\n        const sorting = this.config.quality.options;\n        return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1;\n      })\n      .forEach((quality) => {\n        controls.createMenuItem.call(this, {\n          value: quality,\n          list,\n          type,\n          title: controls.getLabel.call(this, 'quality', quality),\n          badge: getBadge(quality),\n        });\n      });\n\n    controls.updateSetting.call(this, type, list);\n  },\n\n  // Set the looping options\n  /* setLoopMenu() {\n        // Menu required\n        if (!is.element(this.elements.settings.panels.loop)) {\n            return;\n        }\n\n        const options = ['start', 'end', 'all', 'reset'];\n        const list = this.elements.settings.panels.loop.querySelector('[role=\"menu\"]');\n\n        // Show the pane and tab\n        toggleHidden(this.elements.settings.buttons.loop, false);\n        toggleHidden(this.elements.settings.panels.loop, false);\n\n        // Toggle the pane and tab\n        const toggle = !is.empty(this.loop.options);\n        controls.toggleMenuButton.call(this, 'loop', toggle);\n\n        // Empty the menu\n        emptyElement(list);\n\n        options.forEach(option => {\n            const item = createElement('li');\n\n            const button = createElement(\n                'button',\n                extend(getAttributesFromSelector(this.config.selectors.buttons.loop), {\n                    type: 'button',\n                    class: this.config.classNames.control,\n                    'data-plyr-loop-action': option,\n                }),\n                i18n.get(option, this.config)\n            );\n\n            if (['start', 'end'].includes(option)) {\n                const badge = controls.createBadge.call(this, '00:00');\n                button.appendChild(badge);\n            }\n\n            item.appendChild(button);\n            list.appendChild(item);\n        });\n    }, */\n\n  // Get current selected caption language\n  // TODO: rework this to user the getter in the API?\n\n  // Set a list of available captions languages\n  setCaptionsMenu() {\n    // Menu required\n    if (!is.element(this.elements.settings.panels.captions)) {\n      return;\n    }\n\n    // TODO: Captions or language? Currently it's mixed\n    const type = 'captions';\n    const list = this.elements.settings.panels.captions.querySelector('[role=\"menu\"]');\n    const tracks = captions.getTracks.call(this);\n    const toggle = Boolean(tracks.length);\n\n    // Toggle the pane and tab\n    controls.toggleMenuButton.call(this, type, toggle);\n\n    // Empty the menu\n    emptyElement(list);\n\n    // Check if we need to toggle the parent\n    controls.checkMenu.call(this);\n\n    // If there's no captions, bail\n    if (!toggle) {\n      return;\n    }\n\n    // Generate options data\n    const options = tracks.map((track, value) => ({\n      value,\n      checked: this.captions.toggled && this.currentTrack === value,\n      title: captions.getLabel.call(this, track),\n      badge: track.language && controls.createBadge.call(this, track.language.toUpperCase()),\n      list,\n      type: 'language',\n    }));\n\n    // Add the \"Disabled\" option to turn off captions\n    options.unshift({\n      value: -1,\n      checked: !this.captions.toggled,\n      title: i18n.get('disabled', this.config),\n      list,\n      type: 'language',\n    });\n\n    // Generate options\n    options.forEach(controls.createMenuItem.bind(this));\n\n    controls.updateSetting.call(this, type, list);\n  },\n\n  // Set a list of available captions languages\n  setSpeedMenu() {\n    // Menu required\n    if (!is.element(this.elements.settings.panels.speed)) {\n      return;\n    }\n\n    const type = 'speed';\n    const list = this.elements.settings.panels.speed.querySelector('[role=\"menu\"]');\n\n    // Filter out invalid speeds\n    this.options.speed = this.options.speed.filter((o) => o >= this.minimumSpeed && o <= this.maximumSpeed);\n\n    // Toggle the pane and tab\n    const toggle = !is.empty(this.options.speed) && this.options.speed.length > 1;\n    controls.toggleMenuButton.call(this, type, toggle);\n\n    // Empty the menu\n    emptyElement(list);\n\n    // Check if we need to toggle the parent\n    controls.checkMenu.call(this);\n\n    // If we're hiding, nothing more to do\n    if (!toggle) {\n      return;\n    }\n\n    // Create items\n    this.options.speed.forEach((speed) => {\n      controls.createMenuItem.call(this, {\n        value: speed,\n        list,\n        type,\n        title: controls.getLabel.call(this, 'speed', speed),\n      });\n    });\n\n    controls.updateSetting.call(this, type, list);\n  },\n\n  // Check if we need to hide/show the settings menu\n  checkMenu() {\n    const { buttons } = this.elements.settings;\n    const visible = !is.empty(buttons) && Object.values(buttons).some((button) => !button.hidden);\n\n    toggleHidden(this.elements.settings.menu, !visible);\n  },\n\n  // Focus the first menu item in a given (or visible) menu\n  focusFirstMenuItem(pane, tabFocus = false) {\n    if (this.elements.settings.popup.hidden) {\n      return;\n    }\n\n    let target = pane;\n\n    if (!is.element(target)) {\n      target = Object.values(this.elements.settings.panels).find((p) => !p.hidden);\n    }\n\n    const firstItem = target.querySelector('[role^=\"menuitem\"]');\n\n    setFocus.call(this, firstItem, tabFocus);\n  },\n\n  // Show/hide menu\n  toggleMenu(input) {\n    const { popup } = this.elements.settings;\n    const button = this.elements.buttons.settings;\n\n    // Menu and button are required\n    if (!is.element(popup) || !is.element(button)) {\n      return;\n    }\n\n    // True toggle by default\n    const { hidden } = popup;\n    let show = hidden;\n\n    if (is.boolean(input)) {\n      show = input;\n    } else if (is.keyboardEvent(input) && input.which === 27) {\n      show = false;\n    } else if (is.event(input)) {\n      // If Plyr is in a shadowDOM, the event target is set to the component, instead of the\n      // Element in the shadowDOM. The path, if available, is complete.\n      const target = is.function(input.composedPath) ? input.composedPath()[0] : input.target;\n      const isMenuItem = popup.contains(target);\n\n      // If the click was inside the menu or if the click\n      // wasn't the button or menu item and we're trying to\n      // show the menu (a doc click shouldn't show the menu)\n      if (isMenuItem || (!isMenuItem && input.target !== button && show)) {\n        return;\n      }\n    }\n\n    // Set button attributes\n    button.setAttribute('aria-expanded', show);\n\n    // Show the actual popup\n    toggleHidden(popup, !show);\n\n    // Add class hook\n    toggleClass(this.elements.container, this.config.classNames.menu.open, show);\n\n    // Focus the first item if key interaction\n    if (show && is.keyboardEvent(input)) {\n      controls.focusFirstMenuItem.call(this, null, true);\n    } else if (!show && !hidden) {\n      // If closing, re-focus the button\n      setFocus.call(this, button, is.keyboardEvent(input));\n    }\n  },\n\n  // Get the natural size of a menu panel\n  getMenuSize(tab) {\n    const clone = tab.cloneNode(true);\n    clone.style.position = 'absolute';\n    clone.style.opacity = 0;\n    clone.removeAttribute('hidden');\n\n    // Append to parent so we get the \"real\" size\n    tab.parentNode.appendChild(clone);\n\n    // Get the sizes before we remove\n    const width = clone.scrollWidth;\n    const height = clone.scrollHeight;\n\n    // Remove from the DOM\n    removeElement(clone);\n\n    return {\n      width,\n      height,\n    };\n  },\n\n  // Show a panel in the menu\n  showMenuPanel(type = '', tabFocus = false) {\n    const target = this.elements.container.querySelector(`#plyr-settings-${this.id}-${type}`);\n\n    // Nothing to show, bail\n    if (!is.element(target)) {\n      return;\n    }\n\n    // Hide all other panels\n    const container = target.parentNode;\n    const current = Array.from(container.children).find((node) => !node.hidden);\n\n    // If we can do fancy animations, we'll animate the height/width\n    if (support.transitions && !support.reducedMotion) {\n      // Set the current width as a base\n      container.style.width = `${current.scrollWidth}px`;\n      container.style.height = `${current.scrollHeight}px`;\n\n      // Get potential sizes\n      const size = controls.getMenuSize.call(this, target);\n\n      // Restore auto height/width\n      const restore = (event) => {\n        // We're only bothered about height and width on the container\n        if (event.target !== container || !['width', 'height'].includes(event.propertyName)) {\n          return;\n        }\n\n        // Revert back to auto\n        container.style.width = '';\n        container.style.height = '';\n\n        // Only listen once\n        off.call(this, container, transitionEndEvent, restore);\n      };\n\n      // Listen for the transition finishing and restore auto height/width\n      on.call(this, container, transitionEndEvent, restore);\n\n      // Set dimensions to target\n      container.style.width = `${size.width}px`;\n      container.style.height = `${size.height}px`;\n    }\n\n    // Set attributes on current tab\n    toggleHidden(current, true);\n\n    // Set attributes on target\n    toggleHidden(target, false);\n\n    // Focus the first item\n    controls.focusFirstMenuItem.call(this, target, tabFocus);\n  },\n\n  // Set the download URL\n  setDownloadUrl() {\n    const button = this.elements.buttons.download;\n\n    // Bail if no button\n    if (!is.element(button)) {\n      return;\n    }\n\n    // Set attribute\n    button.setAttribute('href', this.download);\n  },\n\n  // Build the default HTML\n  create(data) {\n    const {\n      bindMenuItemShortcuts,\n      createButton,\n      createProgress,\n      createRange,\n      createTime,\n      setQualityMenu,\n      setSpeedMenu,\n      showMenuPanel,\n    } = controls;\n    this.elements.controls = null;\n\n    // Larger overlaid play button\n    if (is.array(this.config.controls) && this.config.controls.includes('play-large')) {\n      this.elements.container.appendChild(createButton.call(this, 'play-large'));\n    }\n\n    // Create the container\n    const container = createElement('div', getAttributesFromSelector(this.config.selectors.controls.wrapper));\n    this.elements.controls = container;\n\n    // Default item attributes\n    const defaultAttributes = { class: 'plyr__controls__item' };\n\n    // Loop through controls in order\n    dedupe(is.array(this.config.controls) ? this.config.controls : []).forEach((control) => {\n      // Restart button\n      if (control === 'restart') {\n        container.appendChild(createButton.call(this, 'restart', defaultAttributes));\n      }\n\n      // Rewind button\n      if (control === 'rewind') {\n        container.appendChild(createButton.call(this, 'rewind', defaultAttributes));\n      }\n\n      // Play/Pause button\n      if (control === 'play') {\n        container.appendChild(createButton.call(this, 'play', defaultAttributes));\n      }\n\n      // Fast forward button\n      if (control === 'fast-forward') {\n        container.appendChild(createButton.call(this, 'fast-forward', defaultAttributes));\n      }\n\n      // Progress\n      if (control === 'progress') {\n        const progressContainer = createElement('div', {\n          class: `${defaultAttributes.class} plyr__progress__container`,\n        });\n\n        const progress = createElement('div', getAttributesFromSelector(this.config.selectors.progress));\n\n        // Seek range slider\n        progress.appendChild(\n          createRange.call(this, 'seek', {\n            id: `plyr-seek-${data.id}`,\n          }),\n        );\n\n        // Buffer progress\n        progress.appendChild(createProgress.call(this, 'buffer'));\n\n        // TODO: Add loop display indicator\n\n        // Seek tooltip\n        if (this.config.tooltips.seek) {\n          const tooltip = createElement(\n            'span',\n            {\n              class: this.config.classNames.tooltip,\n            },\n            '00:00',\n          );\n\n          progress.appendChild(tooltip);\n          this.elements.display.seekTooltip = tooltip;\n        }\n\n        this.elements.progress = progress;\n        progressContainer.appendChild(this.elements.progress);\n        container.appendChild(progressContainer);\n      }\n\n      // Media current time display\n      if (control === 'current-time') {\n        container.appendChild(createTime.call(this, 'currentTime', defaultAttributes));\n      }\n\n      // Media duration display\n      if (control === 'duration') {\n        container.appendChild(createTime.call(this, 'duration', defaultAttributes));\n      }\n\n      // Volume controls\n      if (control === 'mute' || control === 'volume') {\n        let { volume } = this.elements;\n\n        // Create the volume container if needed\n        if (!is.element(volume) || !container.contains(volume)) {\n          volume = createElement(\n            'div',\n            extend({}, defaultAttributes, {\n              class: `${defaultAttributes.class} plyr__volume`.trim(),\n            }),\n          );\n\n          this.elements.volume = volume;\n\n          container.appendChild(volume);\n        }\n\n        // Toggle mute button\n        if (control === 'mute') {\n          volume.appendChild(createButton.call(this, 'mute'));\n        }\n\n        // Volume range control\n        // Ignored on iOS as it's handled globally\n        // https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html\n        if (control === 'volume' && !browser.isIos) {\n          // Set the attributes\n          const attributes = {\n            max: 1,\n            step: 0.05,\n            value: this.config.volume,\n          };\n\n          // Create the volume range slider\n          volume.appendChild(\n            createRange.call(\n              this,\n              'volume',\n              extend(attributes, {\n                id: `plyr-volume-${data.id}`,\n              }),\n            ),\n          );\n        }\n      }\n\n      // Toggle captions button\n      if (control === 'captions') {\n        container.appendChild(createButton.call(this, 'captions', defaultAttributes));\n      }\n\n      // Settings button / menu\n      if (control === 'settings' && !is.empty(this.config.settings)) {\n        const wrapper = createElement(\n          'div',\n          extend({}, defaultAttributes, {\n            class: `${defaultAttributes.class} plyr__menu`.trim(),\n            hidden: '',\n          }),\n        );\n\n        wrapper.appendChild(\n          createButton.call(this, 'settings', {\n            'aria-haspopup': true,\n            'aria-controls': `plyr-settings-${data.id}`,\n            'aria-expanded': false,\n          }),\n        );\n\n        const popup = createElement('div', {\n          class: 'plyr__menu__container',\n          id: `plyr-settings-${data.id}`,\n          hidden: '',\n        });\n\n        const inner = createElement('div');\n\n        const home = createElement('div', {\n          id: `plyr-settings-${data.id}-home`,\n        });\n\n        // Create the menu\n        const menu = createElement('div', {\n          role: 'menu',\n        });\n\n        home.appendChild(menu);\n        inner.appendChild(home);\n        this.elements.settings.panels.home = home;\n\n        // Build the menu items\n        this.config.settings.forEach((type) => {\n          // TODO: bundle this with the createMenuItem helper and bindings\n          const menuItem = createElement(\n            'button',\n            extend(getAttributesFromSelector(this.config.selectors.buttons.settings), {\n              type: 'button',\n              class: `${this.config.classNames.control} ${this.config.classNames.control}--forward`,\n              role: 'menuitem',\n              'aria-haspopup': true,\n              hidden: '',\n            }),\n          );\n\n          // Bind menu shortcuts for keyboard users\n          bindMenuItemShortcuts.call(this, menuItem, type);\n\n          // Show menu on click\n          on.call(this, menuItem, 'click', () => {\n            showMenuPanel.call(this, type, false);\n          });\n\n          const flex = createElement('span', null, i18n.get(type, this.config));\n\n          const value = createElement('span', {\n            class: this.config.classNames.menu.value,\n          });\n\n          // Speed contains HTML entities\n          value.innerHTML = data[type];\n\n          flex.appendChild(value);\n          menuItem.appendChild(flex);\n          menu.appendChild(menuItem);\n\n          // Build the panes\n          const pane = createElement('div', {\n            id: `plyr-settings-${data.id}-${type}`,\n            hidden: '',\n          });\n\n          // Back button\n          const backButton = createElement('button', {\n            type: 'button',\n            class: `${this.config.classNames.control} ${this.config.classNames.control}--back`,\n          });\n\n          // Visible label\n          backButton.appendChild(\n            createElement(\n              'span',\n              {\n                'aria-hidden': true,\n              },\n              i18n.get(type, this.config),\n            ),\n          );\n\n          // Screen reader label\n          backButton.appendChild(\n            createElement(\n              'span',\n              {\n                class: this.config.classNames.hidden,\n              },\n              i18n.get('menuBack', this.config),\n            ),\n          );\n\n          // Go back via keyboard\n          on.call(\n            this,\n            pane,\n            'keydown',\n            (event) => {\n              // We only care about <-\n              if (event.which !== 37) {\n                return;\n              }\n\n              // Prevent seek\n              event.preventDefault();\n              event.stopPropagation();\n\n              // Show the respective menu\n              showMenuPanel.call(this, 'home', true);\n            },\n            false,\n          );\n\n          // Go back via button click\n          on.call(this, backButton, 'click', () => {\n            showMenuPanel.call(this, 'home', false);\n          });\n\n          // Add to pane\n          pane.appendChild(backButton);\n\n          // Menu\n          pane.appendChild(\n            createElement('div', {\n              role: 'menu',\n            }),\n          );\n\n          inner.appendChild(pane);\n\n          this.elements.settings.buttons[type] = menuItem;\n          this.elements.settings.panels[type] = pane;\n        });\n\n        popup.appendChild(inner);\n        wrapper.appendChild(popup);\n        container.appendChild(wrapper);\n\n        this.elements.settings.popup = popup;\n        this.elements.settings.menu = wrapper;\n      }\n\n      // Picture in picture button\n      if (control === 'pip' && support.pip) {\n        container.appendChild(createButton.call(this, 'pip', defaultAttributes));\n      }\n\n      // Airplay button\n      if (control === 'airplay' && support.airplay) {\n        container.appendChild(createButton.call(this, 'airplay', defaultAttributes));\n      }\n\n      // Download button\n      if (control === 'download') {\n        const attributes = extend({}, defaultAttributes, {\n          element: 'a',\n          href: this.download,\n          target: '_blank',\n        });\n\n        // Set download attribute for HTML5 only\n        if (this.isHTML5) {\n          attributes.download = '';\n        }\n\n        const { download } = this.config.urls;\n\n        if (!is.url(download) && this.isEmbed) {\n          extend(attributes, {\n            icon: `logo-${this.provider}`,\n            label: this.provider,\n          });\n        }\n\n        container.appendChild(createButton.call(this, 'download', attributes));\n      }\n\n      // Toggle fullscreen button\n      if (control === 'fullscreen') {\n        container.appendChild(createButton.call(this, 'fullscreen', defaultAttributes));\n      }\n    });\n\n    // Set available quality levels\n    if (this.isHTML5) {\n      setQualityMenu.call(this, html5.getQualityOptions.call(this));\n    }\n\n    setSpeedMenu.call(this);\n\n    return container;\n  },\n\n  // Insert controls\n  inject() {\n    // Sprite\n    if (this.config.loadSprite) {\n      const icon = controls.getIconUrl.call(this);\n\n      // Only load external sprite using AJAX\n      if (icon.cors) {\n        loadSprite(icon.url, 'sprite-plyr');\n      }\n    }\n\n    // Create a unique ID\n    this.id = Math.floor(Math.random() * 10000);\n\n    // Null by default\n    let container = null;\n    this.elements.controls = null;\n\n    // Set template properties\n    const props = {\n      id: this.id,\n      seektime: this.config.seekTime,\n      title: this.config.title,\n    };\n    let update = true;\n\n    // If function, run it and use output\n    if (is.function(this.config.controls)) {\n      this.config.controls = this.config.controls.call(this, props);\n    }\n\n    // Convert falsy controls to empty array (primarily for empty strings)\n    if (!this.config.controls) {\n      this.config.controls = [];\n    }\n\n    if (is.element(this.config.controls) || is.string(this.config.controls)) {\n      // HTMLElement or Non-empty string passed as the option\n      container = this.config.controls;\n    } else {\n      // Create controls\n      container = controls.create.call(this, {\n        id: this.id,\n        seektime: this.config.seekTime,\n        speed: this.speed,\n        quality: this.quality,\n        captions: captions.getLabel.call(this),\n        // TODO: Looping\n        // loop: 'None',\n      });\n      update = false;\n    }\n\n    // Replace props with their value\n    const replace = (input) => {\n      let result = input;\n\n      Object.entries(props).forEach(([key, value]) => {\n        result = replaceAll(result, `{${key}}`, value);\n      });\n\n      return result;\n    };\n\n    // Update markup\n    if (update) {\n      if (is.string(this.config.controls)) {\n        container = replace(container);\n      }\n    }\n\n    // Controls container\n    let target;\n\n    // Inject to custom location\n    if (is.string(this.config.selectors.controls.container)) {\n      target = document.querySelector(this.config.selectors.controls.container);\n    }\n\n    // Inject into the container by default\n    if (!is.element(target)) {\n      target = this.elements.container;\n    }\n\n    // Inject controls HTML (needs to be before captions, hence \"afterbegin\")\n    const insertMethod = is.element(container) ? 'insertAdjacentElement' : 'insertAdjacentHTML';\n    target[insertMethod]('afterbegin', container);\n\n    // Find the elements if need be\n    if (!is.element(this.elements.controls)) {\n      controls.findElements.call(this);\n    }\n\n    // Add pressed property to buttons\n    if (!is.empty(this.elements.buttons)) {\n      const addProperty = (button) => {\n        const className = this.config.classNames.controlPressed;\n        Object.defineProperty(button, 'pressed', {\n          enumerable: true,\n          get() {\n            return hasClass(button, className);\n          },\n          set(pressed = false) {\n            toggleClass(button, className, pressed);\n          },\n        });\n      };\n\n      // Toggle classname when pressed property is set\n      Object.values(this.elements.buttons)\n        .filter(Boolean)\n        .forEach((button) => {\n          if (is.array(button) || is.nodeList(button)) {\n            Array.from(button).filter(Boolean).forEach(addProperty);\n          } else {\n            addProperty(button);\n          }\n        });\n    }\n\n    // Edge sometimes doesn't finish the paint so force a repaint\n    if (browser.isEdge) {\n      repaint(target);\n    }\n\n    // Setup tooltips\n    if (this.config.tooltips.controls) {\n      const { classNames, selectors } = this.config;\n      const selector = `${selectors.controls.wrapper} ${selectors.labels} .${classNames.hidden}`;\n      const labels = getElements.call(this, selector);\n\n      Array.from(labels).forEach((label) => {\n        toggleClass(label, this.config.classNames.hidden, false);\n        toggleClass(label, this.config.classNames.tooltip, true);\n      });\n    }\n  },\n};\n\nexport default controls;\n", "// ==========================================================================\n// URL utils\n// ==========================================================================\n\nimport is from './is';\n\n/**\n * Parse a string to a URL object\n * @param {String} input - the URL to be parsed\n * @param {Boolean} safe - failsafe parsing\n */\nexport function parseUrl(input, safe = true) {\n  let url = input;\n\n  if (safe) {\n    const parser = document.createElement('a');\n    parser.href = url;\n    url = parser.href;\n  }\n\n  try {\n    return new URL(url);\n  } catch (_) {\n    return null;\n  }\n}\n\n// Convert object to URLSearchParams\nexport function buildUrlParams(input) {\n  const params = new URLSearchParams();\n\n  if (is.object(input)) {\n    Object.entries(input).forEach(([key, value]) => {\n      params.set(key, value);\n    });\n  }\n\n  return params;\n}\n", "// ==========================================================================\n// Plyr Captions\n// TODO: Create as class\n// ==========================================================================\n\nimport controls from './controls';\nimport support from './support';\nimport { dedupe } from './utils/arrays';\nimport browser from './utils/browser';\nimport {\n  createElement,\n  emptyElement,\n  getAttributesFromSelector,\n  insertAfter,\n  removeElement,\n  toggleClass,\n} from './utils/elements';\nimport { on, triggerEvent } from './utils/events';\nimport fetch from './utils/fetch';\nimport i18n from './utils/i18n';\nimport is from './utils/is';\nimport { getHTML } from './utils/strings';\nimport { parseUrl } from './utils/urls';\n\nconst captions = {\n  // Setup captions\n  setup() {\n    // Requires UI support\n    if (!this.supported.ui) {\n      return;\n    }\n\n    // Only Vimeo and HTML5 video supported at this point\n    if (!this.isVideo || this.isYouTube || (this.isHTML5 && !support.textTracks)) {\n      // Clear menu and hide\n      if (\n        is.array(this.config.controls) &&\n        this.config.controls.includes('settings') &&\n        this.config.settings.includes('captions')\n      ) {\n        controls.setCaptionsMenu.call(this);\n      }\n\n      return;\n    }\n\n    // Inject the container\n    if (!is.element(this.elements.captions)) {\n      this.elements.captions = createElement('div', getAttributesFromSelector(this.config.selectors.captions));\n\n      insertAfter(this.elements.captions, this.elements.wrapper);\n    }\n\n    // Fix IE captions if CORS is used\n    // Fetch captions and inject as blobs instead (data URIs not supported!)\n    if (browser.isIE && window.URL) {\n      const elements = this.media.querySelectorAll('track');\n\n      Array.from(elements).forEach((track) => {\n        const src = track.getAttribute('src');\n        const url = parseUrl(src);\n\n        if (\n          url !== null &&\n          url.hostname !== window.location.href.hostname &&\n          ['http:', 'https:'].includes(url.protocol)\n        ) {\n          fetch(src, 'blob')\n            .then((blob) => {\n              track.setAttribute('src', window.URL.createObjectURL(blob));\n            })\n            .catch(() => {\n              removeElement(track);\n            });\n        }\n      });\n    }\n\n    // Get and set initial data\n    // The \"preferred\" options are not realized unless / until the wanted language has a match\n    // * languages: Array of user's browser languages.\n    // * language:  The language preferred by user settings or config\n    // * active:    The state preferred by user settings or config\n    // * toggled:   The real captions state\n\n    const browserLanguages = navigator.languages || [navigator.language || navigator.userLanguage || 'en'];\n    const languages = dedupe(browserLanguages.map((language) => language.split('-')[0]));\n    let language = (this.storage.get('language') || this.config.captions.language || 'auto').toLowerCase();\n\n    // Use first browser language when language is 'auto'\n    if (language === 'auto') {\n      [language] = languages;\n    }\n\n    let active = this.storage.get('captions');\n    if (!is.boolean(active)) {\n      ({ active } = this.config.captions);\n    }\n\n    Object.assign(this.captions, {\n      toggled: false,\n      active,\n      language,\n      languages,\n    });\n\n    // Watch changes to textTracks and update captions menu\n    if (this.isHTML5) {\n      const trackEvents = this.config.captions.update ? 'addtrack removetrack' : 'removetrack';\n      on.call(this, this.media.textTracks, trackEvents, captions.update.bind(this));\n    }\n\n    // Update available languages in list next tick (the event must not be triggered before the listeners)\n    setTimeout(captions.update.bind(this), 0);\n  },\n\n  // Update available language options in settings based on tracks\n  update() {\n    const tracks = captions.getTracks.call(this, true);\n    // Get the wanted language\n    const { active, language, meta, currentTrackNode } = this.captions;\n    const languageExists = Boolean(tracks.find((track) => track.language === language));\n\n    // Handle tracks (add event listener and \"pseudo\"-default)\n    if (this.isHTML5 && this.isVideo) {\n      tracks\n        .filter((track) => !meta.get(track))\n        .forEach((track) => {\n          this.debug.log('Track added', track);\n\n          // Attempt to store if the original dom element was \"default\"\n          meta.set(track, {\n            default: track.mode === 'showing',\n          });\n\n          // Turn off native caption rendering to avoid double captions\n          // Note: mode='hidden' forces a track to download. To ensure every track\n          // isn't downloaded at once, only 'showing' tracks should be reassigned\n          // eslint-disable-next-line no-param-reassign\n          if (track.mode === 'showing') {\n            // eslint-disable-next-line no-param-reassign\n            track.mode = 'hidden';\n          }\n\n          // Add event listener for cue changes\n          on.call(this, track, 'cuechange', () => captions.updateCues.call(this));\n        });\n    }\n\n    // Update language first time it matches, or if the previous matching track was removed\n    if ((languageExists && this.language !== language) || !tracks.includes(currentTrackNode)) {\n      captions.setLanguage.call(this, language);\n      captions.toggle.call(this, active && languageExists);\n    }\n\n    // Enable or disable captions based on track length\n    if (this.elements) {\n      toggleClass(this.elements.container, this.config.classNames.captions.enabled, !is.empty(tracks));\n    }\n\n    // Update available languages in list\n    if (\n      is.array(this.config.controls) &&\n      this.config.controls.includes('settings') &&\n      this.config.settings.includes('captions')\n    ) {\n      controls.setCaptionsMenu.call(this);\n    }\n  },\n\n  // Toggle captions display\n  // Used internally for the toggleCaptions method, with the passive option forced to false\n  toggle(input, passive = true) {\n    // If there's no full support\n    if (!this.supported.ui) {\n      return;\n    }\n\n    const { toggled } = this.captions; // Current state\n    const activeClass = this.config.classNames.captions.active;\n    // Get the next state\n    // If the method is called without parameter, toggle based on current value\n    const active = is.nullOrUndefined(input) ? !toggled : input;\n\n    // Update state and trigger event\n    if (active !== toggled) {\n      // When passive, don't override user preferences\n      if (!passive) {\n        this.captions.active = active;\n        this.storage.set({ captions: active });\n      }\n\n      // Force language if the call isn't passive and there is no matching language to toggle to\n      if (!this.language && active && !passive) {\n        const tracks = captions.getTracks.call(this);\n        const track = captions.findTrack.call(this, [this.captions.language, ...this.captions.languages], true);\n\n        // Override user preferences to avoid switching languages if a matching track is added\n        this.captions.language = track.language;\n\n        // Set caption, but don't store in localStorage as user preference\n        captions.set.call(this, tracks.indexOf(track));\n        return;\n      }\n\n      // Toggle button if it's enabled\n      if (this.elements.buttons.captions) {\n        this.elements.buttons.captions.pressed = active;\n      }\n\n      // Add class hook\n      toggleClass(this.elements.container, activeClass, active);\n\n      this.captions.toggled = active;\n\n      // Update settings menu\n      controls.updateSetting.call(this, 'captions');\n\n      // Trigger event (not used internally)\n      triggerEvent.call(this, this.media, active ? 'captionsenabled' : 'captionsdisabled');\n    }\n\n    // Wait for the call stack to clear before setting mode='hidden'\n    // on the active track - forcing the browser to download it\n    setTimeout(() => {\n      if (active && this.captions.toggled) {\n        this.captions.currentTrackNode.mode = 'hidden';\n      }\n    });\n  },\n\n  // Set captions by track index\n  // Used internally for the currentTrack setter with the passive option forced to false\n  set(index, passive = true) {\n    const tracks = captions.getTracks.call(this);\n\n    // Disable captions if setting to -1\n    if (index === -1) {\n      captions.toggle.call(this, false, passive);\n      return;\n    }\n\n    if (!is.number(index)) {\n      this.debug.warn('Invalid caption argument', index);\n      return;\n    }\n\n    if (!(index in tracks)) {\n      this.debug.warn('Track not found', index);\n      return;\n    }\n\n    if (this.captions.currentTrack !== index) {\n      this.captions.currentTrack = index;\n      const track = tracks[index];\n      const { language } = track || {};\n\n      // Store reference to node for invalidation on remove\n      this.captions.currentTrackNode = track;\n\n      // Update settings menu\n      controls.updateSetting.call(this, 'captions');\n\n      // When passive, don't override user preferences\n      if (!passive) {\n        this.captions.language = language;\n        this.storage.set({ language });\n      }\n\n      // Handle Vimeo captions\n      if (this.isVimeo) {\n        this.embed.enableTextTrack(language);\n      }\n\n      // Trigger event\n      triggerEvent.call(this, this.media, 'languagechange');\n    }\n\n    // Show captions\n    captions.toggle.call(this, true, passive);\n\n    if (this.isHTML5 && this.isVideo) {\n      // If we change the active track while a cue is already displayed we need to update it\n      captions.updateCues.call(this);\n    }\n  },\n\n  // Set captions by language\n  // Used internally for the language setter with the passive option forced to false\n  setLanguage(input, passive = true) {\n    if (!is.string(input)) {\n      this.debug.warn('Invalid language argument', input);\n      return;\n    }\n    // Normalize\n    const language = input.toLowerCase();\n    this.captions.language = language;\n\n    // Set currentTrack\n    const tracks = captions.getTracks.call(this);\n    const track = captions.findTrack.call(this, [language]);\n    captions.set.call(this, tracks.indexOf(track), passive);\n  },\n\n  // Get current valid caption tracks\n  // If update is false it will also ignore tracks without metadata\n  // This is used to \"freeze\" the language options when captions.update is false\n  getTracks(update = false) {\n    // Handle media or textTracks missing or null\n    const tracks = Array.from((this.media || {}).textTracks || []);\n    // For HTML5, use cache instead of current tracks when it exists (if captions.update is false)\n    // Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata)\n    return tracks\n      .filter((track) => !this.isHTML5 || update || this.captions.meta.has(track))\n      .filter((track) => ['captions', 'subtitles'].includes(track.kind));\n  },\n\n  // Match tracks based on languages and get the first\n  findTrack(languages, force = false) {\n    const tracks = captions.getTracks.call(this);\n    const sortIsDefault = (track) => Number((this.captions.meta.get(track) || {}).default);\n    const sorted = Array.from(tracks).sort((a, b) => sortIsDefault(b) - sortIsDefault(a));\n    let track;\n\n    languages.every((language) => {\n      track = sorted.find((t) => t.language === language);\n      return !track; // Break iteration if there is a match\n    });\n\n    // If no match is found but is required, get first\n    return track || (force ? sorted[0] : undefined);\n  },\n\n  // Get the current track\n  getCurrentTrack() {\n    return captions.getTracks.call(this)[this.currentTrack];\n  },\n\n  // Get UI label for track\n  getLabel(track) {\n    let currentTrack = track;\n\n    if (!is.track(currentTrack) && support.textTracks && this.captions.toggled) {\n      currentTrack = captions.getCurrentTrack.call(this);\n    }\n\n    if (is.track(currentTrack)) {\n      if (!is.empty(currentTrack.label)) {\n        return currentTrack.label;\n      }\n\n      if (!is.empty(currentTrack.language)) {\n        return track.language.toUpperCase();\n      }\n\n      return i18n.get('enabled', this.config);\n    }\n\n    return i18n.get('disabled', this.config);\n  },\n\n  // Update captions using current track's active cues\n  // Also optional array argument in case there isn't any track (ex: vimeo)\n  updateCues(input) {\n    // Requires UI\n    if (!this.supported.ui) {\n      return;\n    }\n\n    if (!is.element(this.elements.captions)) {\n      this.debug.warn('No captions element to render to');\n      return;\n    }\n\n    // Only accept array or empty input\n    if (!is.nullOrUndefined(input) && !Array.isArray(input)) {\n      this.debug.warn('updateCues: Invalid input', input);\n      return;\n    }\n\n    let cues = input;\n\n    // Get cues from track\n    if (!cues) {\n      const track = captions.getCurrentTrack.call(this);\n\n      cues = Array.from((track || {}).activeCues || [])\n        .map((cue) => cue.getCueAsHTML())\n        .map(getHTML);\n    }\n\n    // Set new caption text\n    const content = cues.map((cueText) => cueText.trim()).join('\\n');\n    const changed = content !== this.elements.captions.innerHTML;\n\n    if (changed) {\n      // Empty the container and create a new child element\n      emptyElement(this.elements.captions);\n      const caption = createElement('span', getAttributesFromSelector(this.config.selectors.caption));\n      caption.innerHTML = content;\n      this.elements.captions.appendChild(caption);\n\n      // Trigger event\n      triggerEvent.call(this, this.media, 'cuechange');\n    }\n  },\n};\n\nexport default captions;\n", "// ==========================================================================\n// Plyr default config\n// ==========================================================================\n\nconst defaults = {\n  // Disable\n  enabled: true,\n\n  // Custom media title\n  title: '',\n\n  // Logging to console\n  debug: false,\n\n  // Auto play (if supported)\n  autoplay: false,\n\n  // Only allow one media playing at once (vimeo only)\n  autopause: true,\n\n  // Allow inline playback on iOS (this effects YouTube/Vimeo - HTML5 requires the attribute present)\n  // TODO: Remove iosNative fullscreen option in favour of this (logic needs work)\n  playsinline: true,\n\n  // Default time to skip when rewind/fast forward\n  seekTime: 10,\n\n  // Default volume\n  volume: 1,\n  muted: false,\n\n  // Pass a custom duration\n  duration: null,\n\n  // Display the media duration on load in the current time position\n  // If you have opted to display both duration and currentTime, this is ignored\n  displayDuration: true,\n\n  // Invert the current time to be a countdown\n  invertTime: true,\n\n  // Clicking the currentTime inverts it's value to show time left rather than elapsed\n  toggleInvert: true,\n\n  // Force an aspect ratio\n  // The format must be `'w:h'` (e.g. `'16:9'`)\n  ratio: null,\n\n  // Click video container to play/pause\n  clickToPlay: true,\n\n  // Auto hide the controls\n  hideControls: true,\n\n  // Reset to start when playback ended\n  resetOnEnd: false,\n\n  // Disable the standard context menu\n  disableContextMenu: true,\n\n  // Sprite (for icons)\n  loadSprite: true,\n  iconPrefix: 'plyr',\n  iconUrl: 'https://cdn.plyr.io/3.6.12/plyr.svg',\n\n  // Blank video (used to prevent errors on source change)\n  blankVideo: 'https://cdn.plyr.io/static/blank.mp4',\n\n  // Quality default\n  quality: {\n    default: 576,\n    // The options to display in the UI, if available for the source media\n    options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240],\n    forced: false,\n    onChange: null,\n  },\n\n  // Set loops\n  loop: {\n    active: false,\n    // start: null,\n    // end: null,\n  },\n\n  // Speed default and options to display\n  speed: {\n    selected: 1,\n    // The options to display in the UI, if available for the source media (e.g. Vimeo and YouTube only support 0.5x-4x)\n    options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 4],\n  },\n\n  // Keyboard shortcut settings\n  keyboard: {\n    focused: true,\n    global: false,\n  },\n\n  // Display tooltips\n  tooltips: {\n    controls: false,\n    seek: true,\n  },\n\n  // Captions settings\n  captions: {\n    active: false,\n    language: 'auto',\n    // Listen to new tracks added after Plyr is initialized.\n    // This is needed for streaming captions, but may result in unselectable options\n    update: false,\n  },\n\n  // Fullscreen settings\n  fullscreen: {\n    enabled: true, // Allow fullscreen?\n    fallback: true, // Fallback using full viewport/window\n    iosNative: false, // Use the native fullscreen in iOS (disables custom controls)\n    // Selector for the fullscreen container so contextual / non-player content can remain visible in fullscreen mode\n    // Non-ancestors of the player element will be ignored\n    // container: null, // defaults to the player element\n  },\n\n  // Local storage\n  storage: {\n    enabled: true,\n    key: 'plyr',\n  },\n\n  // Default controls\n  controls: [\n    'play-large',\n    // 'restart',\n    // 'rewind',\n    'play',\n    // 'fast-forward',\n    'progress',\n    'current-time',\n    // 'duration',\n    'mute',\n    'volume',\n    'captions',\n    'settings',\n    'pip',\n    'airplay',\n    // 'download',\n    'fullscreen',\n  ],\n  settings: ['captions', 'quality', 'speed'],\n\n  // Localisation\n  i18n: {\n    restart: 'Restart',\n    rewind: 'Rewind {seektime}s',\n    play: 'Play',\n    pause: 'Pause',\n    fastForward: 'Forward {seektime}s',\n    seek: 'Seek',\n    seekLabel: '{currentTime} of {duration}',\n    played: 'Played',\n    buffered: 'Buffered',\n    currentTime: 'Current time',\n    duration: 'Duration',\n    volume: 'Volume',\n    mute: 'Mute',\n    unmute: 'Unmute',\n    enableCaptions: 'Enable captions',\n    disableCaptions: 'Disable captions',\n    download: 'Download',\n    enterFullscreen: 'Enter fullscreen',\n    exitFullscreen: 'Exit fullscreen',\n    frameTitle: 'Player for {title}',\n    captions: 'Captions',\n    settings: 'Settings',\n    pip: 'PIP',\n    menuBack: 'Go back to previous menu',\n    speed: 'Speed',\n    normal: 'Normal',\n    quality: 'Quality',\n    loop: 'Loop',\n    start: 'Start',\n    end: 'End',\n    all: 'All',\n    reset: 'Reset',\n    disabled: 'Disabled',\n    enabled: 'Enabled',\n    advertisement: 'Ad',\n    qualityBadge: {\n      2160: '4K',\n      1440: 'HD',\n      1080: 'HD',\n      720: 'HD',\n      576: 'SD',\n      480: 'SD',\n    },\n  },\n\n  // URLs\n  urls: {\n    download: null,\n    vimeo: {\n      sdk: 'https://player.vimeo.com/api/player.js',\n      iframe: 'https://player.vimeo.com/video/{0}?{1}',\n      api: 'https://vimeo.com/api/oembed.json?url={0}',\n    },\n    youtube: {\n      sdk: 'https://www.youtube.com/iframe_api',\n      api: 'https://noembed.com/embed?url=https://www.youtube.com/watch?v={0}',\n    },\n    googleIMA: {\n      sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js',\n    },\n  },\n\n  // Custom control listeners\n  listeners: {\n    seek: null,\n    play: null,\n    pause: null,\n    restart: null,\n    rewind: null,\n    fastForward: null,\n    mute: null,\n    volume: null,\n    captions: null,\n    download: null,\n    fullscreen: null,\n    pip: null,\n    airplay: null,\n    speed: null,\n    quality: null,\n    loop: null,\n    language: null,\n  },\n\n  // Events to watch and bubble\n  events: [\n    // Events to watch on HTML5 media elements and bubble\n    // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events\n    'ended',\n    'progress',\n    'stalled',\n    'playing',\n    'waiting',\n    'canplay',\n    'canplaythrough',\n    'loadstart',\n    'loadeddata',\n    'loadedmetadata',\n    'timeupdate',\n    'volumechange',\n    'play',\n    'pause',\n    'error',\n    'seeking',\n    'seeked',\n    'emptied',\n    'ratechange',\n    'cuechange',\n\n    // Custom events\n    'download',\n    'enterfullscreen',\n    'exitfullscreen',\n    'captionsenabled',\n    'captionsdisabled',\n    'languagechange',\n    'controlshidden',\n    'controlsshown',\n    'ready',\n\n    // YouTube\n    'statechange',\n\n    // Quality\n    'qualitychange',\n\n    // Ads\n    'adsloaded',\n    'adscontentpause',\n    'adscontentresume',\n    'adstarted',\n    'adsmidpoint',\n    'adscomplete',\n    'adsallcomplete',\n    'adsimpression',\n    'adsclick',\n  ],\n\n  // Selectors\n  // Change these to match your template if using custom HTML\n  selectors: {\n    editable: 'input, textarea, select, [contenteditable]',\n    container: '.plyr',\n    controls: {\n      container: null,\n      wrapper: '.plyr__controls',\n    },\n    labels: '[data-plyr]',\n    buttons: {\n      play: '[data-plyr=\"play\"]',\n      pause: '[data-plyr=\"pause\"]',\n      restart: '[data-plyr=\"restart\"]',\n      rewind: '[data-plyr=\"rewind\"]',\n      fastForward: '[data-plyr=\"fast-forward\"]',\n      mute: '[data-plyr=\"mute\"]',\n      captions: '[data-plyr=\"captions\"]',\n      download: '[data-plyr=\"download\"]',\n      fullscreen: '[data-plyr=\"fullscreen\"]',\n      pip: '[data-plyr=\"pip\"]',\n      airplay: '[data-plyr=\"airplay\"]',\n      settings: '[data-plyr=\"settings\"]',\n      loop: '[data-plyr=\"loop\"]',\n    },\n    inputs: {\n      seek: '[data-plyr=\"seek\"]',\n      volume: '[data-plyr=\"volume\"]',\n      speed: '[data-plyr=\"speed\"]',\n      language: '[data-plyr=\"language\"]',\n      quality: '[data-plyr=\"quality\"]',\n    },\n    display: {\n      currentTime: '.plyr__time--current',\n      duration: '.plyr__time--duration',\n      buffer: '.plyr__progress__buffer',\n      loop: '.plyr__progress__loop', // Used later\n      volume: '.plyr__volume--display',\n    },\n    progress: '.plyr__progress',\n    captions: '.plyr__captions',\n    caption: '.plyr__caption',\n  },\n\n  // Class hooks added to the player in different states\n  classNames: {\n    type: 'plyr--{0}',\n    provider: 'plyr--{0}',\n    video: 'plyr__video-wrapper',\n    embed: 'plyr__video-embed',\n    videoFixedRatio: 'plyr__video-wrapper--fixed-ratio',\n    embedContainer: 'plyr__video-embed__container',\n    poster: 'plyr__poster',\n    posterEnabled: 'plyr__poster-enabled',\n    ads: 'plyr__ads',\n    control: 'plyr__control',\n    controlPressed: 'plyr__control--pressed',\n    playing: 'plyr--playing',\n    paused: 'plyr--paused',\n    stopped: 'plyr--stopped',\n    loading: 'plyr--loading',\n    hover: 'plyr--hover',\n    tooltip: 'plyr__tooltip',\n    cues: 'plyr__cues',\n    hidden: 'plyr__sr-only',\n    hideControls: 'plyr--hide-controls',\n    isIos: 'plyr--is-ios',\n    isTouch: 'plyr--is-touch',\n    uiSupported: 'plyr--full-ui',\n    noTransition: 'plyr--no-transition',\n    display: {\n      time: 'plyr__time',\n    },\n    menu: {\n      value: 'plyr__menu__value',\n      badge: 'plyr__badge',\n      open: 'plyr--menu-open',\n    },\n    captions: {\n      enabled: 'plyr--captions-enabled',\n      active: 'plyr--captions-active',\n    },\n    fullscreen: {\n      enabled: 'plyr--fullscreen-enabled',\n      fallback: 'plyr--fullscreen-fallback',\n    },\n    pip: {\n      supported: 'plyr--pip-supported',\n      active: 'plyr--pip-active',\n    },\n    airplay: {\n      supported: 'plyr--airplay-supported',\n      active: 'plyr--airplay-active',\n    },\n    tabFocus: 'plyr__tab-focus',\n    previewThumbnails: {\n      // Tooltip thumbs\n      thumbContainer: 'plyr__preview-thumb',\n      thumbContainerShown: 'plyr__preview-thumb--is-shown',\n      imageContainer: 'plyr__preview-thumb__image-container',\n      timeContainer: 'plyr__preview-thumb__time-container',\n      // Scrubbing\n      scrubbingContainer: 'plyr__preview-scrubbing',\n      scrubbingContainerShown: 'plyr__preview-scrubbing--is-shown',\n    },\n  },\n\n  // Embed attributes\n  attributes: {\n    embed: {\n      provider: 'data-plyr-provider',\n      id: 'data-plyr-embed-id',\n      hash: 'data-plyr-embed-hash',\n    },\n  },\n\n  // Advertisements plugin\n  // Register for an account here: http://vi.ai/publisher-video-monetization/?aid=plyrio\n  ads: {\n    enabled: false,\n    publisherId: '',\n    tagUrl: '',\n  },\n\n  // Preview Thumbnails plugin\n  previewThumbnails: {\n    enabled: false,\n    src: '',\n  },\n\n  // Vimeo plugin\n  vimeo: {\n    byline: false,\n    portrait: false,\n    title: false,\n    speed: true,\n    transparent: false,\n    // Custom settings from Plyr\n    customControls: true,\n    referrerPolicy: null, // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy\n    // Whether the owner of the video has a Pro or Business account\n    // (which allows us to properly hide controls without CSS hacks, etc)\n    premium: false,\n  },\n\n  // YouTube plugin\n  youtube: {\n    rel: 0, // No related vids\n    showinfo: 0, // Hide info\n    iv_load_policy: 3, // Hide annotations\n    modestbranding: 1, // Hide logos as much as possible (they still show one in the corner when paused)\n    // Custom settings from Plyr\n    customControls: true,\n    noCookie: false, // Whether to use an alternative version of YouTube without cookies\n  },\n};\n\nexport default defaults;\n", "// ==========================================================================\n// Plyr states\n// ==========================================================================\n\nexport const pip = {\n  active: 'picture-in-picture',\n  inactive: 'inline',\n};\n\nexport default { pip };\n", "// ==========================================================================\n// Plyr supported types and providers\n// ==========================================================================\n\nexport const providers = {\n  html5: 'html5',\n  youtube: 'youtube',\n  vimeo: 'vimeo',\n};\n\nexport const types = {\n  audio: 'audio',\n  video: 'video',\n};\n\n/**\n * Get provider by URL\n * @param {String} url\n */\nexport function getProviderByUrl(url) {\n  // YouTube\n  if (/^(https?:\\/\\/)?(www\\.)?(youtube\\.com|youtube-nocookie\\.com|youtu\\.?be)\\/.+$/.test(url)) {\n    return providers.youtube;\n  }\n\n  // Vimeo\n  if (/^https?:\\/\\/player.vimeo.com\\/video\\/\\d{0,9}(?=\\b|\\/)/.test(url)) {\n    return providers.vimeo;\n  }\n\n  return null;\n}\n\nexport default { providers, types };\n", "// ==========================================================================\n// Console wrapper\n// ==========================================================================\n\nconst noop = () => {};\n\nexport default class Console {\n  constructor(enabled = false) {\n    this.enabled = window.console && enabled;\n\n    if (this.enabled) {\n      this.log('Debugging enabled');\n    }\n  }\n\n  get log() {\n    // eslint-disable-next-line no-console\n    return this.enabled ? Function.prototype.bind.call(console.log, console) : noop;\n  }\n\n  get warn() {\n    // eslint-disable-next-line no-console\n    return this.enabled ? Function.prototype.bind.call(console.warn, console) : noop;\n  }\n\n  get error() {\n    // eslint-disable-next-line no-console\n    return this.enabled ? Function.prototype.bind.call(console.error, console) : noop;\n  }\n}\n", "// ==========================================================================\n// Fullscreen wrapper\n// https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API#prefixing\n// https://webkit.org/blog/7929/designing-websites-for-iphone-x/\n// ==========================================================================\n\nimport browser from './utils/browser';\nimport { closest, getElements, hasClass, toggleClass } from './utils/elements';\nimport { on, triggerEvent } from './utils/events';\nimport is from './utils/is';\nimport { silencePromise } from './utils/promise';\n\nclass Fullscreen {\n  constructor(player) {\n    // Keep reference to parent\n    this.player = player;\n\n    // Get prefix\n    this.prefix = Fullscreen.prefix;\n    this.property = Fullscreen.property;\n\n    // Scroll position\n    this.scrollPosition = { x: 0, y: 0 };\n\n    // Force the use of 'full window/browser' rather than fullscreen\n    this.forceFallback = player.config.fullscreen.fallback === 'force';\n\n    // Get the fullscreen element\n    // Checks container is an ancestor, defaults to null\n    this.player.elements.fullscreen =\n      player.config.fullscreen.container && closest(this.player.elements.container, player.config.fullscreen.container);\n\n    // Register event listeners\n    // Handle event (incase user presses escape etc)\n    on.call(\n      this.player,\n      document,\n      this.prefix === 'ms' ? 'MSFullscreenChange' : `${this.prefix}fullscreenchange`,\n      () => {\n        // TODO: Filter for target??\n        this.onChange();\n      },\n    );\n\n    // Fullscreen toggle on double click\n    on.call(this.player, this.player.elements.container, 'dblclick', (event) => {\n      // Ignore double click in controls\n      if (is.element(this.player.elements.controls) && this.player.elements.controls.contains(event.target)) {\n        return;\n      }\n\n      this.player.listeners.proxy(event, this.toggle, 'fullscreen');\n    });\n\n    // Tap focus when in fullscreen\n    on.call(this, this.player.elements.container, 'keydown', (event) => this.trapFocus(event));\n\n    // Update the UI\n    this.update();\n\n    // this.toggle = this.toggle.bind(this);\n  }\n\n  // Determine if native supported\n  static get native() {\n    return !!(\n      document.fullscreenEnabled ||\n      document.webkitFullscreenEnabled ||\n      document.mozFullScreenEnabled ||\n      document.msFullscreenEnabled\n    );\n  }\n\n  // If we're actually using native\n  get usingNative() {\n    return Fullscreen.native && !this.forceFallback;\n  }\n\n  // Get the prefix for handlers\n  static get prefix() {\n    // No prefix\n    if (is.function(document.exitFullscreen)) {\n      return '';\n    }\n\n    // Check for fullscreen support by vendor prefix\n    let value = '';\n    const prefixes = ['webkit', 'moz', 'ms'];\n\n    prefixes.some((pre) => {\n      if (is.function(document[`${pre}ExitFullscreen`]) || is.function(document[`${pre}CancelFullScreen`])) {\n        value = pre;\n        return true;\n      }\n\n      return false;\n    });\n\n    return value;\n  }\n\n  static get property() {\n    return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen';\n  }\n\n  // Determine if fullscreen is enabled\n  get enabled() {\n    return (\n      (Fullscreen.native || this.player.config.fullscreen.fallback) &&\n      this.player.config.fullscreen.enabled &&\n      this.player.supported.ui &&\n      this.player.isVideo\n    );\n  }\n\n  // Get active state\n  get active() {\n    if (!this.enabled) {\n      return false;\n    }\n\n    // Fallback using classname\n    if (!Fullscreen.native || this.forceFallback) {\n      return hasClass(this.target, this.player.config.classNames.fullscreen.fallback);\n    }\n\n    const element = !this.prefix\n      ? this.target.getRootNode().fullscreenElement\n      : this.target.getRootNode()[`${this.prefix}${this.property}Element`];\n\n    return element && element.shadowRoot ? element === this.target.getRootNode().host : element === this.target;\n  }\n\n  // Get target element\n  get target() {\n    return browser.isIos && this.player.config.fullscreen.iosNative\n      ? this.player.media\n      : this.player.elements.fullscreen || this.player.elements.container;\n  }\n\n  onChange = () => {\n    if (!this.enabled) {\n      return;\n    }\n\n    // Update toggle button\n    const button = this.player.elements.buttons.fullscreen;\n    if (is.element(button)) {\n      button.pressed = this.active;\n    }\n\n    // Always trigger events on the plyr / media element (not a fullscreen container) and let them bubble up\n    const target = this.target === this.player.media ? this.target : this.player.elements.container;\n    // Trigger an event\n    triggerEvent.call(this.player, target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);\n  };\n\n  toggleFallback = (toggle = false) => {\n    // Store or restore scroll position\n    if (toggle) {\n      this.scrollPosition = {\n        x: window.scrollX || 0,\n        y: window.scrollY || 0,\n      };\n    } else {\n      window.scrollTo(this.scrollPosition.x, this.scrollPosition.y);\n    }\n\n    // Toggle scroll\n    document.body.style.overflow = toggle ? 'hidden' : '';\n\n    // Toggle class hook\n    toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle);\n\n    // Force full viewport on iPhone X+\n    if (browser.isIos) {\n      let viewport = document.head.querySelector('meta[name=\"viewport\"]');\n      const property = 'viewport-fit=cover';\n\n      // Inject the viewport meta if required\n      if (!viewport) {\n        viewport = document.createElement('meta');\n        viewport.setAttribute('name', 'viewport');\n      }\n\n      // Check if the property already exists\n      const hasProperty = is.string(viewport.content) && viewport.content.includes(property);\n\n      if (toggle) {\n        this.cleanupViewport = !hasProperty;\n\n        if (!hasProperty) {\n          viewport.content += `,${property}`;\n        }\n      } else if (this.cleanupViewport) {\n        viewport.content = viewport.content\n          .split(',')\n          .filter((part) => part.trim() !== property)\n          .join(',');\n      }\n    }\n\n    // Toggle button and fire events\n    this.onChange();\n  };\n\n  // Trap focus inside container\n  trapFocus = (event) => {\n    // Bail if iOS, not active, not the tab key\n    if (browser.isIos || !this.active || event.key !== 'Tab' || event.keyCode !== 9) {\n      return;\n    }\n\n    // Get the current focused element\n    const focused = document.activeElement;\n    const focusable = getElements.call(this.player, 'a[href], button:not(:disabled), input:not(:disabled), [tabindex]');\n    const [first] = focusable;\n    const last = focusable[focusable.length - 1];\n\n    if (focused === last && !event.shiftKey) {\n      // Move focus to first element that can be tabbed if Shift isn't used\n      first.focus();\n      event.preventDefault();\n    } else if (focused === first && event.shiftKey) {\n      // Move focus to last element that can be tabbed if Shift is used\n      last.focus();\n      event.preventDefault();\n    }\n  };\n\n  // Update UI\n  update = () => {\n    if (this.enabled) {\n      let mode;\n\n      if (this.forceFallback) {\n        mode = 'Fallback (forced)';\n      } else if (Fullscreen.native) {\n        mode = 'Native';\n      } else {\n        mode = 'Fallback';\n      }\n\n      this.player.debug.log(`${mode} fullscreen enabled`);\n    } else {\n      this.player.debug.log('Fullscreen not supported and fallback disabled');\n    }\n\n    // Add styling hook to show button\n    toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled);\n  };\n\n  // Make an element fullscreen\n  enter = () => {\n    if (!this.enabled) {\n      return;\n    }\n\n    // iOS native fullscreen doesn't need the request step\n    if (browser.isIos && this.player.config.fullscreen.iosNative) {\n      if (this.player.isVimeo) {\n        this.player.embed.requestFullscreen();\n      } else {\n        this.target.webkitEnterFullscreen();\n      }\n    } else if (!Fullscreen.native || this.forceFallback) {\n      this.toggleFallback(true);\n    } else if (!this.prefix) {\n      this.target.requestFullscreen({ navigationUI: 'hide' });\n    } else if (!is.empty(this.prefix)) {\n      this.target[`${this.prefix}Request${this.property}`]();\n    }\n  };\n\n  // Bail from fullscreen\n  exit = () => {\n    if (!this.enabled) {\n      return;\n    }\n\n    // iOS native fullscreen\n    if (browser.isIos && this.player.config.fullscreen.iosNative) {\n      this.target.webkitExitFullscreen();\n      silencePromise(this.player.play());\n    } else if (!Fullscreen.native || this.forceFallback) {\n      this.toggleFallback(false);\n    } else if (!this.prefix) {\n      (document.cancelFullScreen || document.exitFullscreen).call(document);\n    } else if (!is.empty(this.prefix)) {\n      const action = this.prefix === 'moz' ? 'Cancel' : 'Exit';\n      document[`${this.prefix}${action}${this.property}`]();\n    }\n  };\n\n  // Toggle state\n  toggle = () => {\n    if (!this.active) {\n      this.enter();\n    } else {\n      this.exit();\n    }\n  };\n}\n\nexport default Fullscreen;\n", "// ==========================================================================\n// Load image avoiding xhr/fetch CORS issues\n// Server status can't be obtained this way unfortunately, so this uses \"naturalWidth\" to determine if the image has loaded\n// By default it checks if it is at least 1px, but you can add a second argument to change this\n// ==========================================================================\n\nexport default function loadImage(src, minWidth = 1) {\n  return new Promise((resolve, reject) => {\n    const image = new Image();\n\n    const handler = () => {\n      delete image.onload;\n      delete image.onerror;\n      (image.naturalWidth >= minWidth ? resolve : reject)(image);\n    };\n\n    Object.assign(image, { onload: handler, onerror: handler, src });\n  });\n}\n", "// ==========================================================================\n// Plyr UI\n// ==========================================================================\n\nimport captions from './captions';\nimport controls from './controls';\nimport support from './support';\nimport browser from './utils/browser';\nimport { getElement, toggleClass } from './utils/elements';\nimport { ready, triggerEvent } from './utils/events';\nimport i18n from './utils/i18n';\nimport is from './utils/is';\nimport loadImage from './utils/load-image';\n\nconst ui = {\n  addStyleHook() {\n    toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true);\n    toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui);\n  },\n\n  // Toggle native HTML5 media controls\n  toggleNativeControls(toggle = false) {\n    if (toggle && this.isHTML5) {\n      this.media.setAttribute('controls', '');\n    } else {\n      this.media.removeAttribute('controls');\n    }\n  },\n\n  // Setup the UI\n  build() {\n    // Re-attach media element listeners\n    // TODO: Use event bubbling?\n    this.listeners.media();\n\n    // Don't setup interface if no support\n    if (!this.supported.ui) {\n      this.debug.warn(`Basic support only for ${this.provider} ${this.type}`);\n\n      // Restore native controls\n      ui.toggleNativeControls.call(this, true);\n\n      // Bail\n      return;\n    }\n\n    // Inject custom controls if not present\n    if (!is.element(this.elements.controls)) {\n      // Inject custom controls\n      controls.inject.call(this);\n\n      // Re-attach control listeners\n      this.listeners.controls();\n    }\n\n    // Remove native controls\n    ui.toggleNativeControls.call(this);\n\n    // Setup captions for HTML5\n    if (this.isHTML5) {\n      captions.setup.call(this);\n    }\n\n    // Reset volume\n    this.volume = null;\n\n    // Reset mute state\n    this.muted = null;\n\n    // Reset loop state\n    this.loop = null;\n\n    // Reset quality setting\n    this.quality = null;\n\n    // Reset speed\n    this.speed = null;\n\n    // Reset volume display\n    controls.updateVolume.call(this);\n\n    // Reset time display\n    controls.timeUpdate.call(this);\n\n    // Reset duration display\n    controls.durationUpdate.call(this);\n\n    // Update the UI\n    ui.checkPlaying.call(this);\n\n    // Check for picture-in-picture support\n    toggleClass(\n      this.elements.container,\n      this.config.classNames.pip.supported,\n      support.pip && this.isHTML5 && this.isVideo,\n    );\n\n    // Check for airplay support\n    toggleClass(this.elements.container, this.config.classNames.airplay.supported, support.airplay && this.isHTML5);\n\n    // Add iOS class\n    toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos);\n\n    // Add touch class\n    toggleClass(this.elements.container, this.config.classNames.isTouch, this.touch);\n\n    // Ready for API calls\n    this.ready = true;\n\n    // Ready event at end of execution stack\n    setTimeout(() => {\n      triggerEvent.call(this, this.media, 'ready');\n    }, 0);\n\n    // Set the title\n    ui.setTitle.call(this);\n\n    // Assure the poster image is set, if the property was added before the element was created\n    if (this.poster) {\n      ui.setPoster.call(this, this.poster, false).catch(() => {});\n    }\n\n    // Manually set the duration if user has overridden it.\n    // The event listeners for it doesn't get called if preload is disabled (#701)\n    if (this.config.duration) {\n      controls.durationUpdate.call(this);\n    }\n  },\n\n  // Setup aria attribute for play and iframe title\n  setTitle() {\n    // Find the current text\n    let label = i18n.get('play', this.config);\n\n    // If there's a media title set, use that for the label\n    if (is.string(this.config.title) && !is.empty(this.config.title)) {\n      label += `, ${this.config.title}`;\n    }\n\n    // If there's a play button, set label\n    Array.from(this.elements.buttons.play || []).forEach((button) => {\n      button.setAttribute('aria-label', label);\n    });\n\n    // Set iframe title\n    // https://github.com/sampotts/plyr/issues/124\n    if (this.isEmbed) {\n      const iframe = getElement.call(this, 'iframe');\n\n      if (!is.element(iframe)) {\n        return;\n      }\n\n      // Default to media type\n      const title = !is.empty(this.config.title) ? this.config.title : 'video';\n      const format = i18n.get('frameTitle', this.config);\n\n      iframe.setAttribute('title', format.replace('{title}', title));\n    }\n  },\n\n  // Toggle poster\n  togglePoster(enable) {\n    toggleClass(this.elements.container, this.config.classNames.posterEnabled, enable);\n  },\n\n  // Set the poster image (async)\n  // Used internally for the poster setter, with the passive option forced to false\n  setPoster(poster, passive = true) {\n    // Don't override if call is passive\n    if (passive && this.poster) {\n      return Promise.reject(new Error('Poster already set'));\n    }\n\n    // Set property synchronously to respect the call order\n    this.media.setAttribute('data-poster', poster);\n\n    // Show the poster\n    this.elements.poster.removeAttribute('hidden');\n\n    // Wait until ui is ready\n    return (\n      ready\n        .call(this)\n        // Load image\n        .then(() => loadImage(poster))\n        .catch((error) => {\n          // Hide poster on error unless it's been set by another call\n          if (poster === this.poster) {\n            ui.togglePoster.call(this, false);\n          }\n          // Rethrow\n          throw error;\n        })\n        .then(() => {\n          // Prevent race conditions\n          if (poster !== this.poster) {\n            throw new Error('setPoster cancelled by later call to setPoster');\n          }\n        })\n        .then(() => {\n          Object.assign(this.elements.poster.style, {\n            backgroundImage: `url('${poster}')`,\n            // Reset backgroundSize as well (since it can be set to \"cover\" for padded thumbnails for youtube)\n            backgroundSize: '',\n          });\n\n          ui.togglePoster.call(this, true);\n\n          return poster;\n        })\n    );\n  },\n\n  // Check playing state\n  checkPlaying(event) {\n    // Class hooks\n    toggleClass(this.elements.container, this.config.classNames.playing, this.playing);\n    toggleClass(this.elements.container, this.config.classNames.paused, this.paused);\n    toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped);\n\n    // Set state\n    Array.from(this.elements.buttons.play || []).forEach((target) => {\n      Object.assign(target, { pressed: this.playing });\n      target.setAttribute('aria-label', i18n.get(this.playing ? 'pause' : 'play', this.config));\n    });\n\n    // Only update controls on non timeupdate events\n    if (is.event(event) && event.type === 'timeupdate') {\n      return;\n    }\n\n    // Toggle controls\n    ui.toggleControls.call(this);\n  },\n\n  // Check if media is loading\n  checkLoading(event) {\n    this.loading = ['stalled', 'waiting'].includes(event.type);\n\n    // Clear timer\n    clearTimeout(this.timers.loading);\n\n    // Timer to prevent flicker when seeking\n    this.timers.loading = setTimeout(\n      () => {\n        // Update progress bar loading class state\n        toggleClass(this.elements.container, this.config.classNames.loading, this.loading);\n\n        // Update controls visibility\n        ui.toggleControls.call(this);\n      },\n      this.loading ? 250 : 0,\n    );\n  },\n\n  // Toggle controls based on state and `force` argument\n  toggleControls(force) {\n    const { controls: controlsElement } = this.elements;\n\n    if (controlsElement && this.config.hideControls) {\n      // Don't hide controls if a touch-device user recently seeked. (Must be limited to touch devices, or it occasionally prevents desktop controls from hiding.)\n      const recentTouchSeek = this.touch && this.lastSeekTime + 2000 > Date.now();\n\n      // Show controls if force, loading, paused, button interaction, or recent seek, otherwise hide\n      this.toggleControls(\n        Boolean(\n          force || this.loading || this.paused || controlsElement.pressed || controlsElement.hover || recentTouchSeek,\n        ),\n      );\n    }\n  },\n\n  // Migrate any custom properties from the media to the parent\n  migrateStyles() {\n    // Loop through values (as they are the keys when the object is spread \uD83E\uDD14)\n    Object.values({ ...this.media.style })\n      // We're only fussed about Plyr specific properties\n      .filter((key) => !is.empty(key) && is.string(key) && key.startsWith('--plyr'))\n      .forEach((key) => {\n        // Set on the container\n        this.elements.container.style.setProperty(key, this.media.style.getPropertyValue(key));\n\n        // Clean up from media element\n        this.media.style.removeProperty(key);\n      });\n\n    // Remove attribute if empty\n    if (is.empty(this.media.style)) {\n      this.media.removeAttribute('style');\n    }\n  },\n};\n\nexport default ui;\n", "// ==========================================================================\n// Plyr Event Listeners\n// ==========================================================================\n\nimport controls from './controls';\nimport ui from './ui';\nimport { repaint } from './utils/animation';\nimport browser from './utils/browser';\nimport { getElement, getElements, matches, toggleClass } from './utils/elements';\nimport { off, on, once, toggleListener, triggerEvent } from './utils/events';\nimport is from './utils/is';\nimport { silencePromise } from './utils/promise';\nimport { getAspectRatio, getViewportSize, supportsCSS } from './utils/style';\n\nclass Listeners {\n  constructor(player) {\n    this.player = player;\n    this.lastKey = null;\n    this.focusTimer = null;\n    this.lastKeyDown = null;\n\n    this.handleKey = this.handleKey.bind(this);\n    this.toggleMenu = this.toggleMenu.bind(this);\n    this.setTabFocus = this.setTabFocus.bind(this);\n    this.firstTouch = this.firstTouch.bind(this);\n  }\n\n  // Handle key presses\n  handleKey(event) {\n    const { player } = this;\n    const { elements } = player;\n    const code = event.keyCode ? event.keyCode : event.which;\n    const pressed = event.type === 'keydown';\n    const repeat = pressed && code === this.lastKey;\n\n    // Bail if a modifier key is set\n    if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {\n      return;\n    }\n\n    // If the event is bubbled from the media element\n    // Firefox doesn't get the keycode for whatever reason\n    if (!is.number(code)) {\n      return;\n    }\n\n    // Seek by the number keys\n    const seekByKey = () => {\n      // Divide the max duration into 10th's and times by the number value\n      player.currentTime = (player.duration / 10) * (code - 48);\n    };\n\n    // Handle the key on keydown\n    // Reset on keyup\n    if (pressed) {\n      // Check focused element\n      // and if the focused element is not editable (e.g. text input)\n      // and any that accept key input http://webaim.org/techniques/keyboard/\n      const focused = document.activeElement;\n      if (is.element(focused)) {\n        const { editable } = player.config.selectors;\n        const { seek } = elements.inputs;\n\n        if (focused !== seek && matches(focused, editable)) {\n          return;\n        }\n\n        if (event.which === 32 && matches(focused, 'button, [role^=\"menuitem\"]')) {\n          return;\n        }\n      }\n\n      // Which keycodes should we prevent default\n      const preventDefault = [32, 37, 38, 39, 40, 48, 49, 50, 51, 52, 53, 54, 56, 57, 67, 70, 73, 75, 76, 77, 79];\n\n      // If the code is found prevent default (e.g. prevent scrolling for arrows)\n      if (preventDefault.includes(code)) {\n        event.preventDefault();\n        event.stopPropagation();\n      }\n\n      switch (code) {\n        case 48:\n        case 49:\n        case 50:\n        case 51:\n        case 52:\n        case 53:\n        case 54:\n        case 55:\n        case 56:\n        case 57:\n          // 0-9\n          if (!repeat) {\n            seekByKey();\n          }\n          break;\n\n        case 32:\n        case 75:\n          // Space and K key\n          if (!repeat) {\n            silencePromise(player.togglePlay());\n          }\n          break;\n\n        case 38:\n          // Arrow up\n          player.increaseVolume(0.1);\n          break;\n\n        case 40:\n          // Arrow down\n          player.decreaseVolume(0.1);\n          break;\n\n        case 77:\n          // M key\n          if (!repeat) {\n            player.muted = !player.muted;\n          }\n          break;\n\n        case 39:\n          // Arrow forward\n          player.forward();\n          break;\n\n        case 37:\n          // Arrow back\n          player.rewind();\n          break;\n\n        case 70:\n          // F key\n          player.fullscreen.toggle();\n          break;\n\n        case 67:\n          // C key\n          if (!repeat) {\n            player.toggleCaptions();\n          }\n          break;\n\n        case 76:\n          // L key\n          player.loop = !player.loop;\n          break;\n\n        /* case 73:\n          this.setLoop('start');\n          break;\n\n        case 76:\n          this.setLoop();\n          break;\n\n        case 79:\n          this.setLoop('end');\n          break; */\n\n        default:\n          break;\n      }\n\n      // Escape is handle natively when in full screen\n      // So we only need to worry about non native\n      if (code === 27 && !player.fullscreen.usingNative && player.fullscreen.active) {\n        player.fullscreen.toggle();\n      }\n\n      // Store last code for next cycle\n      this.lastKey = code;\n    } else {\n      this.lastKey = null;\n    }\n  }\n\n  // Toggle menu\n  toggleMenu(event) {\n    controls.toggleMenu.call(this.player, event);\n  }\n\n  // Device is touch enabled\n  firstTouch = () => {\n    const { player } = this;\n    const { elements } = player;\n\n    player.touch = true;\n\n    // Add touch class\n    toggleClass(elements.container, player.config.classNames.isTouch, true);\n  };\n\n  setTabFocus = (event) => {\n    const { player } = this;\n    const { elements } = player;\n\n    clearTimeout(this.focusTimer);\n\n    // Ignore any key other than tab\n    if (event.type === 'keydown' && event.which !== 9) {\n      return;\n    }\n\n    // Store reference to event timeStamp\n    if (event.type === 'keydown') {\n      this.lastKeyDown = event.timeStamp;\n    }\n\n    // Remove current classes\n    const removeCurrent = () => {\n      const className = player.config.classNames.tabFocus;\n      const current = getElements.call(player, `.${className}`);\n      toggleClass(current, className, false);\n    };\n\n    // Determine if a key was pressed to trigger this event\n    const wasKeyDown = event.timeStamp - this.lastKeyDown <= 20;\n\n    // Ignore focus events if a key was pressed prior\n    if (event.type === 'focus' && !wasKeyDown) {\n      return;\n    }\n\n    // Remove all current\n    removeCurrent();\n\n    // Delay the adding of classname until the focus has changed\n    // This event fires before the focusin event\n    if (event.type !== 'focusout') {\n      this.focusTimer = setTimeout(() => {\n        const focused = document.activeElement;\n\n        // Ignore if current focus element isn't inside the player\n        if (!elements.container.contains(focused)) {\n          return;\n        }\n\n        toggleClass(document.activeElement, player.config.classNames.tabFocus, true);\n      }, 10);\n    }\n  };\n\n  // Global window & document listeners\n  global = (toggle = true) => {\n    const { player } = this;\n\n    // Keyboard shortcuts\n    if (player.config.keyboard.global) {\n      toggleListener.call(player, window, 'keydown keyup', this.handleKey, toggle, false);\n    }\n\n    // Click anywhere closes menu\n    toggleListener.call(player, document.body, 'click', this.toggleMenu, toggle);\n\n    // Detect touch by events\n    once.call(player, document.body, 'touchstart', this.firstTouch);\n\n    // Tab focus detection\n    toggleListener.call(player, document.body, 'keydown focus blur focusout', this.setTabFocus, toggle, false, true);\n  };\n\n  // Container listeners\n  container = () => {\n    const { player } = this;\n    const { config, elements, timers } = player;\n\n    // Keyboard shortcuts\n    if (!config.keyboard.global && config.keyboard.focused) {\n      on.call(player, elements.container, 'keydown keyup', this.handleKey, false);\n    }\n\n    // Toggle controls on mouse events and entering fullscreen\n    on.call(\n      player,\n      elements.container,\n      'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen',\n      (event) => {\n        const { controls: controlsElement } = elements;\n\n        // Remove button states for fullscreen\n        if (controlsElement && event.type === 'enterfullscreen') {\n          controlsElement.pressed = false;\n          controlsElement.hover = false;\n        }\n\n        // Show, then hide after a timeout unless another control event occurs\n        const show = ['touchstart', 'touchmove', 'mousemove'].includes(event.type);\n        let delay = 0;\n\n        if (show) {\n          ui.toggleControls.call(player, true);\n          // Use longer timeout for touch devices\n          delay = player.touch ? 3000 : 2000;\n        }\n\n        // Clear timer\n        clearTimeout(timers.controls);\n\n        // Set new timer to prevent flicker when seeking\n        timers.controls = setTimeout(() => ui.toggleControls.call(player, false), delay);\n      },\n    );\n\n    // Set a gutter for Vimeo\n    const setGutter = () => {\n      if (!player.isVimeo || player.config.vimeo.premium) {\n        return;\n      }\n\n      const target = elements.wrapper;\n      const { active } = player.fullscreen;\n      const [videoWidth, videoHeight] = getAspectRatio.call(player);\n      const useNativeAspectRatio = supportsCSS(`aspect-ratio: ${videoWidth} / ${videoHeight}`);\n\n      // If not active, remove styles\n      if (!active) {\n        if (useNativeAspectRatio) {\n          target.style.width = null;\n          target.style.height = null;\n        } else {\n          target.style.maxWidth = null;\n          target.style.margin = null;\n        }\n        return;\n      }\n\n      // Determine which dimension will overflow and constrain view\n      const [viewportWidth, viewportHeight] = getViewportSize();\n      const overflow = viewportWidth / viewportHeight > videoWidth / videoHeight;\n\n      if (useNativeAspectRatio) {\n        target.style.width = overflow ? 'auto' : '100%';\n        target.style.height = overflow ? '100%' : 'auto';\n      } else {\n        target.style.maxWidth = overflow ? `${(viewportHeight / videoHeight) * videoWidth}px` : null;\n        target.style.margin = overflow ? '0 auto' : null;\n      }\n    };\n\n    // Handle resizing\n    const resized = () => {\n      clearTimeout(timers.resized);\n      timers.resized = setTimeout(setGutter, 50);\n    };\n\n    on.call(player, elements.container, 'enterfullscreen exitfullscreen', (event) => {\n      const { target } = player.fullscreen;\n\n      // Ignore events not from target\n      if (target !== elements.container) {\n        return;\n      }\n\n      // If it's not an embed and no ratio specified\n      if (!player.isEmbed && is.empty(player.config.ratio)) {\n        return;\n      }\n\n      // Set Vimeo gutter\n      setGutter();\n\n      // Watch for resizes\n      const method = event.type === 'enterfullscreen' ? on : off;\n      method.call(player, window, 'resize', resized);\n    });\n  };\n\n  // Listen for media events\n  media = () => {\n    const { player } = this;\n    const { elements } = player;\n\n    // Time change on media\n    on.call(player, player.media, 'timeupdate seeking seeked', (event) => controls.timeUpdate.call(player, event));\n\n    // Display duration\n    on.call(player, player.media, 'durationchange loadeddata loadedmetadata', (event) =>\n      controls.durationUpdate.call(player, event),\n    );\n\n    // Handle the media finishing\n    on.call(player, player.media, 'ended', () => {\n      // Show poster on end\n      if (player.isHTML5 && player.isVideo && player.config.resetOnEnd) {\n        // Restart\n        player.restart();\n\n        // Call pause otherwise IE11 will start playing the video again\n        player.pause();\n      }\n    });\n\n    // Check for buffer progress\n    on.call(player, player.media, 'progress playing seeking seeked', (event) =>\n      controls.updateProgress.call(player, event),\n    );\n\n    // Handle volume changes\n    on.call(player, player.media, 'volumechange', (event) => controls.updateVolume.call(player, event));\n\n    // Handle play/pause\n    on.call(player, player.media, 'playing play pause ended emptied timeupdate', (event) =>\n      ui.checkPlaying.call(player, event),\n    );\n\n    // Loading state\n    on.call(player, player.media, 'waiting canplay seeked playing', (event) => ui.checkLoading.call(player, event));\n\n    // Click video\n    if (player.supported.ui && player.config.clickToPlay && !player.isAudio) {\n      // Re-fetch the wrapper\n      const wrapper = getElement.call(player, `.${player.config.classNames.video}`);\n\n      // Bail if there's no wrapper (this should never happen)\n      if (!is.element(wrapper)) {\n        return;\n      }\n\n      // On click play, pause or restart\n      on.call(player, elements.container, 'click', (event) => {\n        const targets = [elements.container, wrapper];\n\n        // Ignore if click if not container or in video wrapper\n        if (!targets.includes(event.target) && !wrapper.contains(event.target)) {\n          return;\n        }\n\n        // Touch devices will just show controls (if hidden)\n        if (player.touch && player.config.hideControls) {\n          return;\n        }\n\n        if (player.ended) {\n          this.proxy(event, player.restart, 'restart');\n          this.proxy(\n            event,\n            () => {\n              silencePromise(player.play());\n            },\n            'play',\n          );\n        } else {\n          this.proxy(\n            event,\n            () => {\n              silencePromise(player.togglePlay());\n            },\n            'play',\n          );\n        }\n      });\n    }\n\n    // Disable right click\n    if (player.supported.ui && player.config.disableContextMenu) {\n      on.call(\n        player,\n        elements.wrapper,\n        'contextmenu',\n        (event) => {\n          event.preventDefault();\n        },\n        false,\n      );\n    }\n\n    // Volume change\n    on.call(player, player.media, 'volumechange', () => {\n      // Save to storage\n      player.storage.set({\n        volume: player.volume,\n        muted: player.muted,\n      });\n    });\n\n    // Speed change\n    on.call(player, player.media, 'ratechange', () => {\n      // Update UI\n      controls.updateSetting.call(player, 'speed');\n\n      // Save to storage\n      player.storage.set({ speed: player.speed });\n    });\n\n    // Quality change\n    on.call(player, player.media, 'qualitychange', (event) => {\n      // Update UI\n      controls.updateSetting.call(player, 'quality', null, event.detail.quality);\n    });\n\n    // Update download link when ready and if quality changes\n    on.call(player, player.media, 'ready qualitychange', () => {\n      controls.setDownloadUrl.call(player);\n    });\n\n    // Proxy events to container\n    // Bubble up key events for Edge\n    const proxyEvents = player.config.events.concat(['keyup', 'keydown']).join(' ');\n\n    on.call(player, player.media, proxyEvents, (event) => {\n      let { detail = {} } = event;\n\n      // Get error details from media\n      if (event.type === 'error') {\n        detail = player.media.error;\n      }\n\n      triggerEvent.call(player, elements.container, event.type, true, detail);\n    });\n  };\n\n  // Run default and custom handlers\n  proxy = (event, defaultHandler, customHandlerKey) => {\n    const { player } = this;\n    const customHandler = player.config.listeners[customHandlerKey];\n    const hasCustomHandler = is.function(customHandler);\n    let returned = true;\n\n    // Execute custom handler\n    if (hasCustomHandler) {\n      returned = customHandler.call(player, event);\n    }\n\n    // Only call default handler if not prevented in custom handler\n    if (returned !== false && is.function(defaultHandler)) {\n      defaultHandler.call(player, event);\n    }\n  };\n\n  // Trigger custom and default handlers\n  bind = (element, type, defaultHandler, customHandlerKey, passive = true) => {\n    const { player } = this;\n    const customHandler = player.config.listeners[customHandlerKey];\n    const hasCustomHandler = is.function(customHandler);\n\n    on.call(\n      player,\n      element,\n      type,\n      (event) => this.proxy(event, defaultHandler, customHandlerKey),\n      passive && !hasCustomHandler,\n    );\n  };\n\n  // Listen for control events\n  controls = () => {\n    const { player } = this;\n    const { elements } = player;\n    // IE doesn't support input event, so we fallback to change\n    const inputEvent = browser.isIE ? 'change' : 'input';\n\n    // Play/pause toggle\n    if (elements.buttons.play) {\n      Array.from(elements.buttons.play).forEach((button) => {\n        this.bind(\n          button,\n          'click',\n          () => {\n            silencePromise(player.togglePlay());\n          },\n          'play',\n        );\n      });\n    }\n\n    // Pause\n    this.bind(elements.buttons.restart, 'click', player.restart, 'restart');\n\n    // Rewind\n    this.bind(\n      elements.buttons.rewind,\n      'click',\n      () => {\n        // Record seek time so we can prevent hiding controls for a few seconds after rewind\n        player.lastSeekTime = Date.now();\n        player.rewind();\n      },\n      'rewind',\n    );\n\n    // Rewind\n    this.bind(\n      elements.buttons.fastForward,\n      'click',\n      () => {\n        // Record seek time so we can prevent hiding controls for a few seconds after fast forward\n        player.lastSeekTime = Date.now();\n        player.forward();\n      },\n      'fastForward',\n    );\n\n    // Mute toggle\n    this.bind(\n      elements.buttons.mute,\n      'click',\n      () => {\n        player.muted = !player.muted;\n      },\n      'mute',\n    );\n\n    // Captions toggle\n    this.bind(elements.buttons.captions, 'click', () => player.toggleCaptions());\n\n    // Download\n    this.bind(\n      elements.buttons.download,\n      'click',\n      () => {\n        triggerEvent.call(player, player.media, 'download');\n      },\n      'download',\n    );\n\n    // Fullscreen toggle\n    this.bind(\n      elements.buttons.fullscreen,\n      'click',\n      () => {\n        player.fullscreen.toggle();\n      },\n      'fullscreen',\n    );\n\n    // Picture-in-Picture\n    this.bind(\n      elements.buttons.pip,\n      'click',\n      () => {\n        player.pip = 'toggle';\n      },\n      'pip',\n    );\n\n    // Airplay\n    this.bind(elements.buttons.airplay, 'click', player.airplay, 'airplay');\n\n    // Settings menu - click toggle\n    this.bind(\n      elements.buttons.settings,\n      'click',\n      (event) => {\n        // Prevent the document click listener closing the menu\n        event.stopPropagation();\n        event.preventDefault();\n\n        controls.toggleMenu.call(player, event);\n      },\n      null,\n      false,\n    ); // Can't be passive as we're preventing default\n\n    // Settings menu - keyboard toggle\n    // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus\n    // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143\n    this.bind(\n      elements.buttons.settings,\n      'keyup',\n      (event) => {\n        const code = event.which;\n\n        // We only care about space and return\n        if (![13, 32].includes(code)) {\n          return;\n        }\n\n        // Because return triggers a click anyway, all we need to do is set focus\n        if (code === 13) {\n          controls.focusFirstMenuItem.call(player, null, true);\n          return;\n        }\n\n        // Prevent scroll\n        event.preventDefault();\n\n        // Prevent playing video (Firefox)\n        event.stopPropagation();\n\n        // Toggle menu\n        controls.toggleMenu.call(player, event);\n      },\n      null,\n      false, // Can't be passive as we're preventing default\n    );\n\n    // Escape closes menu\n    this.bind(elements.settings.menu, 'keydown', (event) => {\n      if (event.which === 27) {\n        controls.toggleMenu.call(player, event);\n      }\n    });\n\n    // Set range input alternative \"value\", which matches the tooltip time (#954)\n    this.bind(elements.inputs.seek, 'mousedown mousemove', (event) => {\n      const rect = elements.progress.getBoundingClientRect();\n      const percent = (100 / rect.width) * (event.pageX - rect.left);\n      event.currentTarget.setAttribute('seek-value', percent);\n    });\n\n    // Pause while seeking\n    this.bind(elements.inputs.seek, 'mousedown mouseup keydown keyup touchstart touchend', (event) => {\n      const seek = event.currentTarget;\n      const code = event.keyCode ? event.keyCode : event.which;\n      const attribute = 'play-on-seeked';\n\n      if (is.keyboardEvent(event) && code !== 39 && code !== 37) {\n        return;\n      }\n\n      // Record seek time so we can prevent hiding controls for a few seconds after seek\n      player.lastSeekTime = Date.now();\n\n      // Was playing before?\n      const play = seek.hasAttribute(attribute);\n      // Done seeking\n      const done = ['mouseup', 'touchend', 'keyup'].includes(event.type);\n\n      // If we're done seeking and it was playing, resume playback\n      if (play && done) {\n        seek.removeAttribute(attribute);\n        silencePromise(player.play());\n      } else if (!done && player.playing) {\n        seek.setAttribute(attribute, '');\n        player.pause();\n      }\n    });\n\n    // Fix range inputs on iOS\n    // Super weird iOS bug where after you interact with an <input type=\"range\">,\n    // it takes over further interactions on the page. This is a hack\n    if (browser.isIos) {\n      const inputs = getElements.call(player, 'input[type=\"range\"]');\n      Array.from(inputs).forEach((input) => this.bind(input, inputEvent, (event) => repaint(event.target)));\n    }\n\n    // Seek\n    this.bind(\n      elements.inputs.seek,\n      inputEvent,\n      (event) => {\n        const seek = event.currentTarget;\n        // If it exists, use seek-value instead of \"value\" for consistency with tooltip time (#954)\n        let seekTo = seek.getAttribute('seek-value');\n\n        if (is.empty(seekTo)) {\n          seekTo = seek.value;\n        }\n\n        seek.removeAttribute('seek-value');\n\n        player.currentTime = (seekTo / seek.max) * player.duration;\n      },\n      'seek',\n    );\n\n    // Seek tooltip\n    this.bind(elements.progress, 'mouseenter mouseleave mousemove', (event) =>\n      controls.updateSeekTooltip.call(player, event),\n    );\n\n    // Preview thumbnails plugin\n    // TODO: Really need to work on some sort of plug-in wide event bus or pub-sub for this\n    this.bind(elements.progress, 'mousemove touchmove', (event) => {\n      const { previewThumbnails } = player;\n\n      if (previewThumbnails && previewThumbnails.loaded) {\n        previewThumbnails.startMove(event);\n      }\n    });\n\n    // Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering\n    this.bind(elements.progress, 'mouseleave touchend click', () => {\n      const { previewThumbnails } = player;\n\n      if (previewThumbnails && previewThumbnails.loaded) {\n        previewThumbnails.endMove(false, true);\n      }\n    });\n\n    // Show scrubbing preview\n    this.bind(elements.progress, 'mousedown touchstart', (event) => {\n      const { previewThumbnails } = player;\n\n      if (previewThumbnails && previewThumbnails.loaded) {\n        previewThumbnails.startScrubbing(event);\n      }\n    });\n\n    this.bind(elements.progress, 'mouseup touchend', (event) => {\n      const { previewThumbnails } = player;\n\n      if (previewThumbnails && previewThumbnails.loaded) {\n        previewThumbnails.endScrubbing(event);\n      }\n    });\n\n    // Polyfill for lower fill in <input type=\"range\"> for webkit\n    if (browser.isWebkit) {\n      Array.from(getElements.call(player, 'input[type=\"range\"]')).forEach((element) => {\n        this.bind(element, 'input', (event) => controls.updateRangeFill.call(player, event.target));\n      });\n    }\n\n    // Current time invert\n    // Only if one time element is used for both currentTime and duration\n    if (player.config.toggleInvert && !is.element(elements.display.duration)) {\n      this.bind(elements.display.currentTime, 'click', () => {\n        // Do nothing if we're at the start\n        if (player.currentTime === 0) {\n          return;\n        }\n\n        player.config.invertTime = !player.config.invertTime;\n\n        controls.timeUpdate.call(player);\n      });\n    }\n\n    // Volume\n    this.bind(\n      elements.inputs.volume,\n      inputEvent,\n      (event) => {\n        player.volume = event.target.value;\n      },\n      'volume',\n    );\n\n    // Update controls.hover state (used for ui.toggleControls to avoid hiding when interacting)\n    this.bind(elements.controls, 'mouseenter mouseleave', (event) => {\n      elements.controls.hover = !player.touch && event.type === 'mouseenter';\n    });\n\n    // Also update controls.hover state for any non-player children of fullscreen element (as above)\n    if (elements.fullscreen) {\n      Array.from(elements.fullscreen.children)\n        .filter((c) => !c.contains(elements.container))\n        .forEach((child) => {\n          this.bind(child, 'mouseenter mouseleave', (event) => {\n            if (elements.controls) {\n              elements.controls.hover = !player.touch && event.type === 'mouseenter';\n            }\n          });\n        });\n    }\n\n    // Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting)\n    this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', (event) => {\n      elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type);\n    });\n\n    // Show controls when they receive focus (e.g., when using keyboard tab key)\n    this.bind(elements.controls, 'focusin', () => {\n      const { config, timers } = player;\n\n      // Skip transition to prevent focus from scrolling the parent element\n      toggleClass(elements.controls, config.classNames.noTransition, true);\n\n      // Toggle\n      ui.toggleControls.call(player, true);\n\n      // Restore transition\n      setTimeout(() => {\n        toggleClass(elements.controls, config.classNames.noTransition, false);\n      }, 0);\n\n      // Delay a little more for mouse users\n      const delay = this.touch ? 3000 : 4000;\n\n      // Clear timer\n      clearTimeout(timers.controls);\n\n      // Hide again after delay\n      timers.controls = setTimeout(() => ui.toggleControls.call(player, false), delay);\n    });\n\n    // Mouse wheel for volume\n    this.bind(\n      elements.inputs.volume,\n      'wheel',\n      (event) => {\n        // Detect \"natural\" scroll - suppored on OS X Safari only\n        // Other browsers on OS X will be inverted until support improves\n        const inverted = event.webkitDirectionInvertedFromDevice;\n        // Get delta from event. Invert if `inverted` is true\n        const [x, y] = [event.deltaX, -event.deltaY].map((value) => (inverted ? -value : value));\n        // Using the biggest delta, normalize to 1 or -1 (or 0 if no delta)\n        const direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y);\n\n        // Change the volume by 2%\n        player.increaseVolume(direction / 50);\n\n        // Don't break page scrolling at max and min\n        const { volume } = player.media;\n        if ((direction === 1 && volume < 1) || (direction === -1 && volume > 0)) {\n          event.preventDefault();\n        }\n      },\n      'volume',\n      false,\n    );\n  };\n}\n\nexport default Listeners;\n", "(function(root, factory) {\n  if (typeof define === 'function' && define.amd) {\n    define([], factory);\n  } else if (typeof exports === 'object') {\n    module.exports = factory();\n  } else {\n    root.loadjs = factory();\n  }\n}(this, function() {\n/**\n * Global dependencies.\n * @global {Object} document - DOM\n */\n\nvar devnull = function() {},\n    bundleIdCache = {},\n    bundleResultCache = {},\n    bundleCallbackQueue = {};\n\n\n/**\n * Subscribe to bundle load event.\n * @param {string[]} bundleIds - Bundle ids\n * @param {Function} callbackFn - The callback function\n */\nfunction subscribe(bundleIds, callbackFn) {\n  // listify\n  bundleIds = bundleIds.push ? bundleIds : [bundleIds];\n\n  var depsNotFound = [],\n      i = bundleIds.length,\n      numWaiting = i,\n      fn,\n      bundleId,\n      r,\n      q;\n\n  // define callback function\n  fn = function (bundleId, pathsNotFound) {\n    if (pathsNotFound.length) depsNotFound.push(bundleId);\n\n    numWaiting--;\n    if (!numWaiting) callbackFn(depsNotFound);\n  };\n\n  // register callback\n  while (i--) {\n    bundleId = bundleIds[i];\n\n    // execute callback if in result cache\n    r = bundleResultCache[bundleId];\n    if (r) {\n      fn(bundleId, r);\n      continue;\n    }\n\n    // add to callback queue\n    q = bundleCallbackQueue[bundleId] = bundleCallbackQueue[bundleId] || [];\n    q.push(fn);\n  }\n}\n\n\n/**\n * Publish bundle load event.\n * @param {string} bundleId - Bundle id\n * @param {string[]} pathsNotFound - List of files not found\n */\nfunction publish(bundleId, pathsNotFound) {\n  // exit if id isn't defined\n  if (!bundleId) return;\n\n  var q = bundleCallbackQueue[bundleId];\n\n  // cache result\n  bundleResultCache[bundleId] = pathsNotFound;\n\n  // exit if queue is empty\n  if (!q) return;\n\n  // empty callback queue\n  while (q.length) {\n    q[0](bundleId, pathsNotFound);\n    q.splice(0, 1);\n  }\n}\n\n\n/**\n * Execute callbacks.\n * @param {Object or Function} args - The callback args\n * @param {string[]} depsNotFound - List of dependencies not found\n */\nfunction executeCallbacks(args, depsNotFound) {\n  // accept function as argument\n  if (args.call) args = {success: args};\n\n  // success and error callbacks\n  if (depsNotFound.length) (args.error || devnull)(depsNotFound);\n  else (args.success || devnull)(args);\n}\n\n\n/**\n * Load individual file.\n * @param {string} path - The file path\n * @param {Function} callbackFn - The callback function\n */\nfunction loadFile(path, callbackFn, args, numTries) {\n  var doc = document,\n      async = args.async,\n      maxTries = (args.numRetries || 0) + 1,\n      beforeCallbackFn = args.before || devnull,\n      pathname = path.replace(/[\\?|#].*$/, ''),\n      pathStripped = path.replace(/^(css|img)!/, ''),\n      isLegacyIECss,\n      e;\n\n  numTries = numTries || 0;\n\n  if (/(^css!|\\.css$)/.test(pathname)) {\n    // css\n    e = doc.createElement('link');\n    e.rel = 'stylesheet';\n    e.href = pathStripped;\n\n    // tag IE9+\n    isLegacyIECss = 'hideFocus' in e;\n\n    // use preload in IE Edge (to detect load errors)\n    if (isLegacyIECss && e.relList) {\n      isLegacyIECss = 0;\n      e.rel = 'preload';\n      e.as = 'style';\n    }\n  } else if (/(^img!|\\.(png|gif|jpg|svg|webp)$)/.test(pathname)) {\n    // image\n    e = doc.createElement('img');\n    e.src = pathStripped;    \n  } else {\n    // javascript\n    e = doc.createElement('script');\n    e.src = path;\n    e.async = async === undefined ? true : async;\n  }\n\n  e.onload = e.onerror = e.onbeforeload = function (ev) {\n    var result = ev.type[0];\n\n    // treat empty stylesheets as failures to get around lack of onerror\n    // support in IE9-11\n    if (isLegacyIECss) {\n      try {\n        if (!e.sheet.cssText.length) result = 'e';\n      } catch (x) {\n        // sheets objects created from load errors don't allow access to\n        // `cssText` (unless error is Code:18 SecurityError)\n        if (x.code != 18) result = 'e';\n      }\n    }\n\n    // handle retries in case of load failure\n    if (result == 'e') {\n      // increment counter\n      numTries += 1;\n\n      // exit function and try again\n      if (numTries < maxTries) {\n        return loadFile(path, callbackFn, args, numTries);\n      }\n    } else if (e.rel == 'preload' && e.as == 'style') {\n      // activate preloaded stylesheets\n      return e.rel = 'stylesheet'; // jshint ignore:line\n    }\n    \n    // execute callback\n    callbackFn(path, result, ev.defaultPrevented);\n  };\n\n  // add to document (unless callback returns `false`)\n  if (beforeCallbackFn(path, e) !== false) doc.head.appendChild(e);\n}\n\n\n/**\n * Load multiple files.\n * @param {string[]} paths - The file paths\n * @param {Function} callbackFn - The callback function\n */\nfunction loadFiles(paths, callbackFn, args) {\n  // listify paths\n  paths = paths.push ? paths : [paths];\n\n  var numWaiting = paths.length,\n      x = numWaiting,\n      pathsNotFound = [],\n      fn,\n      i;\n\n  // define callback function\n  fn = function(path, result, defaultPrevented) {\n    // handle error\n    if (result == 'e') pathsNotFound.push(path);\n\n    // handle beforeload event. If defaultPrevented then that means the load\n    // will be blocked (ex. Ghostery/ABP on Safari)\n    if (result == 'b') {\n      if (defaultPrevented) pathsNotFound.push(path);\n      else return;\n    }\n\n    numWaiting--;\n    if (!numWaiting) callbackFn(pathsNotFound);\n  };\n\n  // load scripts\n  for (i=0; i < x; i++) loadFile(paths[i], fn, args);\n}\n\n\n/**\n * Initiate script load and register bundle.\n * @param {(string|string[])} paths - The file paths\n * @param {(string|Function|Object)} [arg1] - The (1) bundleId or (2) success\n *   callback or (3) object literal with success/error arguments, numRetries,\n *   etc.\n * @param {(Function|Object)} [arg2] - The (1) success callback or (2) object\n *   literal with success/error arguments, numRetries, etc.\n */\nfunction loadjs(paths, arg1, arg2) {\n  var bundleId,\n      args;\n\n  // bundleId (if string)\n  if (arg1 && arg1.trim) bundleId = arg1;\n\n  // args (default is {})\n  args = (bundleId ? arg2 : arg1) || {};\n\n  // throw error if bundle is already defined\n  if (bundleId) {\n    if (bundleId in bundleIdCache) {\n      throw \"LoadJS\";\n    } else {\n      bundleIdCache[bundleId] = true;\n    }\n  }\n\n  function loadFn(resolve, reject) {\n    loadFiles(paths, function (pathsNotFound) {\n      // execute callbacks\n      executeCallbacks(args, pathsNotFound);\n      \n      // resolve Promise\n      if (resolve) {\n        executeCallbacks({success: resolve, error: reject}, pathsNotFound);\n      }\n\n      // publish bundle load event\n      publish(bundleId, pathsNotFound);\n    }, args);\n  }\n  \n  if (args.returnPromise) return new Promise(loadFn);\n  else loadFn();\n}\n\n\n/**\n * Execute callbacks when dependencies have been satisfied.\n * @param {(string|string[])} deps - List of bundle ids\n * @param {Object} args - success/error arguments\n */\nloadjs.ready = function ready(deps, args) {\n  // subscribe to bundle load event\n  subscribe(deps, function (depsNotFound) {\n    // execute callbacks\n    executeCallbacks(args, depsNotFound);\n  });\n\n  return loadjs;\n};\n\n\n/**\n * Manually satisfy bundle dependencies.\n * @param {string} bundleId - The bundle id\n */\nloadjs.done = function done(bundleId) {\n  publish(bundleId, []);\n};\n\n\n/**\n * Reset loadjs dependencies statuses\n */\nloadjs.reset = function reset() {\n  bundleIdCache = {};\n  bundleResultCache = {};\n  bundleCallbackQueue = {};\n};\n\n\n/**\n * Determine if bundle has already been defined\n * @param String} bundleId - The bundle id\n */\nloadjs.isDefined = function isDefined(bundleId) {\n  return bundleId in bundleIdCache;\n};\n\n\n// export\nreturn loadjs;\n\n}));\n", "// ==========================================================================\n// Load an external script\n// ==========================================================================\n\nimport loadjs from 'loadjs';\n\nexport default function loadScript(url) {\n  return new Promise((resolve, reject) => {\n    loadjs(url, {\n      success: resolve,\n      error: reject,\n    });\n  });\n}\n", "// ==========================================================================\n// Vimeo plugin\n// ==========================================================================\n\nimport captions from '../captions';\nimport controls from '../controls';\nimport ui from '../ui';\nimport { createElement, replaceElement, toggleClass } from '../utils/elements';\nimport { triggerEvent } from '../utils/events';\nimport fetch from '../utils/fetch';\nimport is from '../utils/is';\nimport loadScript from '../utils/load-script';\nimport { format, stripHTML } from '../utils/strings';\nimport { roundAspectRatio, setAspectRatio } from '../utils/style';\nimport { buildUrlParams } from '../utils/urls';\n\n// Parse Vimeo ID from URL\nfunction parseId(url) {\n  if (is.empty(url)) {\n    return null;\n  }\n\n  if (is.number(Number(url))) {\n    return url;\n  }\n\n  const regex = /^.*(vimeo.com\\/|video\\/)(\\d+).*/;\n  return url.match(regex) ? RegExp.$2 : url;\n}\n\n// Try to extract a hash for private videos from the URL\nfunction parseHash(url) {\n  /* This regex matches a hexadecimal hash if given in any of these forms:\n   *  - [https://player.]vimeo.com/video/{id}/{hash}[?params]\n   *  - [https://player.]vimeo.com/video/{id}?h={hash}[&params]\n   *  - [https://player.]vimeo.com/video/{id}?[params]&h={hash}\n   *  - video/{id}/{hash}\n   * If matched, the hash is available in the named group `hash`\n   */\n  const regex = /^.*(?:vimeo.com\\/|video\\/)(?:\\d+)(?:\\?.*&*h=|\\/)+(?<hash>[\\d,a-f]+)/;\n  const found = url.match(regex);\n\n  return found ? found.groups.hash : null;\n}\n\n// Set playback state and trigger change (only on actual change)\nfunction assurePlaybackState(play) {\n  if (play && !this.embed.hasPlayed) {\n    this.embed.hasPlayed = true;\n  }\n  if (this.media.paused === play) {\n    this.media.paused = !play;\n    triggerEvent.call(this, this.media, play ? 'play' : 'pause');\n  }\n}\n\nconst vimeo = {\n  setup() {\n    const player = this;\n\n    // Add embed class for responsive\n    toggleClass(player.elements.wrapper, player.config.classNames.embed, true);\n\n    // Set speed options from config\n    player.options.speed = player.config.speed.options;\n\n    // Set intial ratio\n    setAspectRatio.call(player);\n\n    // Load the SDK if not already\n    if (!is.object(window.Vimeo)) {\n      loadScript(player.config.urls.vimeo.sdk)\n        .then(() => {\n          vimeo.ready.call(player);\n        })\n        .catch((error) => {\n          player.debug.warn('Vimeo SDK (player.js) failed to load', error);\n        });\n    } else {\n      vimeo.ready.call(player);\n    }\n  },\n\n  // API Ready\n  ready() {\n    const player = this;\n    const config = player.config.vimeo;\n    const { premium, referrerPolicy, ...frameParams } = config;\n    // Get the source URL or ID\n    let source = player.media.getAttribute('src');\n    let hash = '';\n    // Get from <div> if needed\n    if (is.empty(source)) {\n      source = player.media.getAttribute(player.config.attributes.embed.id);\n      // hash can also be set as attribute on the <div>\n      hash = player.media.getAttribute(player.config.attributes.embed.hash);\n    } else {\n      hash = parseHash(source);\n    }\n    const hashParam = hash ? { h: hash } : {};\n\n    // If the owner has a pro or premium account then we can hide controls etc\n    if (premium) {\n      Object.assign(frameParams, {\n        controls: false,\n        sidedock: false,\n      });\n    }\n\n    // Get Vimeo params for the iframe\n    const params = buildUrlParams({\n      loop: player.config.loop.active,\n      autoplay: player.autoplay,\n      muted: player.muted,\n      gesture: 'media',\n      playsinline: !this.config.fullscreen.iosNative,\n      // hash has to be added to iframe-URL\n      ...hashParam,\n      ...frameParams,\n    });\n\n    const id = parseId(source);\n    // Build an iframe\n    const iframe = createElement('iframe');\n    const src = format(player.config.urls.vimeo.iframe, id, params);\n    iframe.setAttribute('src', src);\n    iframe.setAttribute('allowfullscreen', '');\n    iframe.setAttribute(\n      'allow',\n      ['autoplay', 'fullscreen', 'picture-in-picture', 'encrypted-media', 'accelerometer', 'gyroscope'].join('; '),\n    );\n\n    // Set the referrer policy if required\n    if (!is.empty(referrerPolicy)) {\n      iframe.setAttribute('referrerPolicy', referrerPolicy);\n    }\n\n    // Inject the package\n    if (premium || !config.customControls) {\n      iframe.setAttribute('data-poster', player.poster);\n      player.media = replaceElement(iframe, player.media);\n    } else {\n      const wrapper = createElement('div', {\n        class: player.config.classNames.embedContainer,\n        'data-poster': player.poster,\n      });\n      wrapper.appendChild(iframe);\n      player.media = replaceElement(wrapper, player.media);\n    }\n\n    // Get poster image\n    if (!config.customControls) {\n      fetch(format(player.config.urls.vimeo.api, src)).then((response) => {\n        if (is.empty(response) || !response.thumbnail_url) {\n          return;\n        }\n\n        // Set and show poster\n        ui.setPoster.call(player, response.thumbnail_url).catch(() => {});\n      });\n    }\n\n    // Setup instance\n    // https://github.com/vimeo/player.js\n    player.embed = new window.Vimeo.Player(iframe, {\n      autopause: player.config.autopause,\n      muted: player.muted,\n    });\n\n    player.media.paused = true;\n    player.media.currentTime = 0;\n\n    // Disable native text track rendering\n    if (player.supported.ui) {\n      player.embed.disableTextTrack();\n    }\n\n    // Create a faux HTML5 API using the Vimeo API\n    player.media.play = () => {\n      assurePlaybackState.call(player, true);\n      return player.embed.play();\n    };\n\n    player.media.pause = () => {\n      assurePlaybackState.call(player, false);\n      return player.embed.pause();\n    };\n\n    player.media.stop = () => {\n      player.pause();\n      player.currentTime = 0;\n    };\n\n    // Seeking\n    let { currentTime } = player.media;\n    Object.defineProperty(player.media, 'currentTime', {\n      get() {\n        return currentTime;\n      },\n      set(time) {\n        // Vimeo will automatically play on seek if the video hasn't been played before\n\n        // Get current paused state and volume etc\n        const { embed, media, paused, volume } = player;\n        const restorePause = paused && !embed.hasPlayed;\n\n        // Set seeking state and trigger event\n        media.seeking = true;\n        triggerEvent.call(player, media, 'seeking');\n\n        // If paused, mute until seek is complete\n        Promise.resolve(restorePause && embed.setVolume(0))\n          // Seek\n          .then(() => embed.setCurrentTime(time))\n          // Restore paused\n          .then(() => restorePause && embed.pause())\n          // Restore volume\n          .then(() => restorePause && embed.setVolume(volume))\n          .catch(() => {\n            // Do nothing\n          });\n      },\n    });\n\n    // Playback speed\n    let speed = player.config.speed.selected;\n    Object.defineProperty(player.media, 'playbackRate', {\n      get() {\n        return speed;\n      },\n      set(input) {\n        player.embed\n          .setPlaybackRate(input)\n          .then(() => {\n            speed = input;\n            triggerEvent.call(player, player.media, 'ratechange');\n          })\n          .catch(() => {\n            // Cannot set Playback Rate, Video is probably not on Pro account\n            player.options.speed = [1];\n          });\n      },\n    });\n\n    // Volume\n    let { volume } = player.config;\n    Object.defineProperty(player.media, 'volume', {\n      get() {\n        return volume;\n      },\n      set(input) {\n        player.embed.setVolume(input).then(() => {\n          volume = input;\n          triggerEvent.call(player, player.media, 'volumechange');\n        });\n      },\n    });\n\n    // Muted\n    let { muted } = player.config;\n    Object.defineProperty(player.media, 'muted', {\n      get() {\n        return muted;\n      },\n      set(input) {\n        const toggle = is.boolean(input) ? input : false;\n\n        player.embed.setVolume(toggle ? 0 : player.config.volume).then(() => {\n          muted = toggle;\n          triggerEvent.call(player, player.media, 'volumechange');\n        });\n      },\n    });\n\n    // Loop\n    let { loop } = player.config;\n    Object.defineProperty(player.media, 'loop', {\n      get() {\n        return loop;\n      },\n      set(input) {\n        const toggle = is.boolean(input) ? input : player.config.loop.active;\n\n        player.embed.setLoop(toggle).then(() => {\n          loop = toggle;\n        });\n      },\n    });\n\n    // Source\n    let currentSrc;\n    player.embed\n      .getVideoUrl()\n      .then((value) => {\n        currentSrc = value;\n        controls.setDownloadUrl.call(player);\n      })\n      .catch((error) => {\n        this.debug.warn(error);\n      });\n\n    Object.defineProperty(player.media, 'currentSrc', {\n      get() {\n        return currentSrc;\n      },\n    });\n\n    // Ended\n    Object.defineProperty(player.media, 'ended', {\n      get() {\n        return player.currentTime === player.duration;\n      },\n    });\n\n    // Set aspect ratio based on video size\n    Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then((dimensions) => {\n      const [width, height] = dimensions;\n      player.embed.ratio = roundAspectRatio(width, height);\n      setAspectRatio.call(this);\n    });\n\n    // Set autopause\n    player.embed.setAutopause(player.config.autopause).then((state) => {\n      player.config.autopause = state;\n    });\n\n    // Get title\n    player.embed.getVideoTitle().then((title) => {\n      player.config.title = title;\n      ui.setTitle.call(this);\n    });\n\n    // Get current time\n    player.embed.getCurrentTime().then((value) => {\n      currentTime = value;\n      triggerEvent.call(player, player.media, 'timeupdate');\n    });\n\n    // Get duration\n    player.embed.getDuration().then((value) => {\n      player.media.duration = value;\n      triggerEvent.call(player, player.media, 'durationchange');\n    });\n\n    // Get captions\n    player.embed.getTextTracks().then((tracks) => {\n      player.media.textTracks = tracks;\n      captions.setup.call(player);\n    });\n\n    player.embed.on('cuechange', ({ cues = [] }) => {\n      const strippedCues = cues.map((cue) => stripHTML(cue.text));\n      captions.updateCues.call(player, strippedCues);\n    });\n\n    player.embed.on('loaded', () => {\n      // Assure state and events are updated on autoplay\n      player.embed.getPaused().then((paused) => {\n        assurePlaybackState.call(player, !paused);\n        if (!paused) {\n          triggerEvent.call(player, player.media, 'playing');\n        }\n      });\n\n      if (is.element(player.embed.element) && player.supported.ui) {\n        const frame = player.embed.element;\n\n        // Fix keyboard focus issues\n        // https://github.com/sampotts/plyr/issues/317\n        frame.setAttribute('tabindex', -1);\n      }\n    });\n\n    player.embed.on('bufferstart', () => {\n      triggerEvent.call(player, player.media, 'waiting');\n    });\n\n    player.embed.on('bufferend', () => {\n      triggerEvent.call(player, player.media, 'playing');\n    });\n\n    player.embed.on('play', () => {\n      assurePlaybackState.call(player, true);\n      triggerEvent.call(player, player.media, 'playing');\n    });\n\n    player.embed.on('pause', () => {\n      assurePlaybackState.call(player, false);\n    });\n\n    player.embed.on('timeupdate', (data) => {\n      player.media.seeking = false;\n      currentTime = data.seconds;\n      triggerEvent.call(player, player.media, 'timeupdate');\n    });\n\n    player.embed.on('progress', (data) => {\n      player.media.buffered = data.percent;\n      triggerEvent.call(player, player.media, 'progress');\n\n      // Check all loaded\n      if (parseInt(data.percent, 10) === 1) {\n        triggerEvent.call(player, player.media, 'canplaythrough');\n      }\n\n      // Get duration as if we do it before load, it gives an incorrect value\n      // https://github.com/sampotts/plyr/issues/891\n      player.embed.getDuration().then((value) => {\n        if (value !== player.media.duration) {\n          player.media.duration = value;\n          triggerEvent.call(player, player.media, 'durationchange');\n        }\n      });\n    });\n\n    player.embed.on('seeked', () => {\n      player.media.seeking = false;\n      triggerEvent.call(player, player.media, 'seeked');\n    });\n\n    player.embed.on('ended', () => {\n      player.media.paused = true;\n      triggerEvent.call(player, player.media, 'ended');\n    });\n\n    player.embed.on('error', (detail) => {\n      player.media.error = detail;\n      triggerEvent.call(player, player.media, 'error');\n    });\n\n    // Rebuild UI\n    if (config.customControls) {\n      setTimeout(() => ui.build.call(player), 0);\n    }\n  },\n};\n\nexport default vimeo;\n", "// ==========================================================================\n// YouTube plugin\n// ==========================================================================\n\nimport ui from '../ui';\nimport { createElement, replaceElement, toggleClass } from '../utils/elements';\nimport { triggerEvent } from '../utils/events';\nimport fetch from '../utils/fetch';\nimport is from '../utils/is';\nimport loadImage from '../utils/load-image';\nimport loadScript from '../utils/load-script';\nimport { extend } from '../utils/objects';\nimport { format, generateId } from '../utils/strings';\nimport { roundAspectRatio, setAspectRatio } from '../utils/style';\n\n// Parse YouTube ID from URL\nfunction parseId(url) {\n  if (is.empty(url)) {\n    return null;\n  }\n\n  const regex = /^.*(youtu.be\\/|v\\/|u\\/\\w\\/|embed\\/|watch\\?v=|&v=)([^#&?]*).*/;\n  return url.match(regex) ? RegExp.$2 : url;\n}\n\n// Set playback state and trigger change (only on actual change)\nfunction assurePlaybackState(play) {\n  if (play && !this.embed.hasPlayed) {\n    this.embed.hasPlayed = true;\n  }\n  if (this.media.paused === play) {\n    this.media.paused = !play;\n    triggerEvent.call(this, this.media, play ? 'play' : 'pause');\n  }\n}\n\nfunction getHost(config) {\n  if (config.noCookie) {\n    return 'https://www.youtube-nocookie.com';\n  }\n\n  if (window.location.protocol === 'http:') {\n    return 'http://www.youtube.com';\n  }\n\n  // Use YouTube's default\n  return undefined;\n}\n\nconst youtube = {\n  setup() {\n    // Add embed class for responsive\n    toggleClass(this.elements.wrapper, this.config.classNames.embed, true);\n\n    // Setup API\n    if (is.object(window.YT) && is.function(window.YT.Player)) {\n      youtube.ready.call(this);\n    } else {\n      // Reference current global callback\n      const callback = window.onYouTubeIframeAPIReady;\n\n      // Set callback to process queue\n      window.onYouTubeIframeAPIReady = () => {\n        // Call global callback if set\n        if (is.function(callback)) {\n          callback();\n        }\n\n        youtube.ready.call(this);\n      };\n\n      // Load the SDK\n      loadScript(this.config.urls.youtube.sdk).catch((error) => {\n        this.debug.warn('YouTube API failed to load', error);\n      });\n    }\n  },\n\n  // Get the media title\n  getTitle(videoId) {\n    const url = format(this.config.urls.youtube.api, videoId);\n\n    fetch(url)\n      .then((data) => {\n        if (is.object(data)) {\n          const { title, height, width } = data;\n\n          // Set title\n          this.config.title = title;\n          ui.setTitle.call(this);\n\n          // Set aspect ratio\n          this.embed.ratio = roundAspectRatio(width, height);\n        }\n\n        setAspectRatio.call(this);\n      })\n      .catch(() => {\n        // Set aspect ratio\n        setAspectRatio.call(this);\n      });\n  },\n\n  // API ready\n  ready() {\n    const player = this;\n    const config = player.config.youtube;\n    // Ignore already setup (race condition)\n    const currentId = player.media && player.media.getAttribute('id');\n    if (!is.empty(currentId) && currentId.startsWith('youtube-')) {\n      return;\n    }\n\n    // Get the source URL or ID\n    let source = player.media.getAttribute('src');\n\n    // Get from <div> if needed\n    if (is.empty(source)) {\n      source = player.media.getAttribute(this.config.attributes.embed.id);\n    }\n\n    // Replace the <iframe> with a <div> due to YouTube API issues\n    const videoId = parseId(source);\n    const id = generateId(player.provider);\n    // Replace media element\n    const container = createElement('div', { id, 'data-poster': config.customControls ? player.poster : undefined });\n    player.media = replaceElement(container, player.media);\n\n    // Only load the poster when using custom controls\n    if (config.customControls) {\n      const posterSrc = (s) => `https://i.ytimg.com/vi/${videoId}/${s}default.jpg`;\n\n      // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide)\n      loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded\n        .catch(() => loadImage(posterSrc('sd'), 121)) // 480p padded 4:3\n        .catch(() => loadImage(posterSrc('hq'))) // 360p padded 4:3. Always exists\n        .then((image) => ui.setPoster.call(player, image.src))\n        .then((src) => {\n          // If the image is padded, use background-size \"cover\" instead (like youtube does too with their posters)\n          if (!src.includes('maxres')) {\n            player.elements.poster.style.backgroundSize = 'cover';\n          }\n        })\n        .catch(() => {});\n    }\n\n    // Setup instance\n    // https://developers.google.com/youtube/iframe_api_reference\n    player.embed = new window.YT.Player(player.media, {\n      videoId,\n      host: getHost(config),\n      playerVars: extend(\n        {},\n        {\n          // Autoplay\n          autoplay: player.config.autoplay ? 1 : 0,\n          // iframe interface language\n          hl: player.config.hl,\n          // Only show controls if not fully supported or opted out\n          controls: player.supported.ui && config.customControls ? 0 : 1,\n          // Disable keyboard as we handle it\n          disablekb: 1,\n          // Allow iOS inline playback\n          playsinline: !player.config.fullscreen.iosNative ? 1 : 0,\n          // Captions are flaky on YouTube\n          cc_load_policy: player.captions.active ? 1 : 0,\n          cc_lang_pref: player.config.captions.language,\n          // Tracking for stats\n          widget_referrer: window ? window.location.href : null,\n        },\n        config,\n      ),\n      events: {\n        onError(event) {\n          // YouTube may fire onError twice, so only handle it once\n          if (!player.media.error) {\n            const code = event.data;\n            // Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError\n            const message =\n              {\n                2: 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.',\n                5: 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.',\n                100: 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.',\n                101: 'The owner of the requested video does not allow it to be played in embedded players.',\n                150: 'The owner of the requested video does not allow it to be played in embedded players.',\n              }[code] || 'An unknown error occured';\n\n            player.media.error = { code, message };\n\n            triggerEvent.call(player, player.media, 'error');\n          }\n        },\n        onPlaybackRateChange(event) {\n          // Get the instance\n          const instance = event.target;\n\n          // Get current speed\n          player.media.playbackRate = instance.getPlaybackRate();\n\n          triggerEvent.call(player, player.media, 'ratechange');\n        },\n        onReady(event) {\n          // Bail if onReady has already been called. See issue #1108\n          if (is.function(player.media.play)) {\n            return;\n          }\n          // Get the instance\n          const instance = event.target;\n\n          // Get the title\n          youtube.getTitle.call(player, videoId);\n\n          // Create a faux HTML5 API using the YouTube API\n          player.media.play = () => {\n            assurePlaybackState.call(player, true);\n            instance.playVideo();\n          };\n\n          player.media.pause = () => {\n            assurePlaybackState.call(player, false);\n            instance.pauseVideo();\n          };\n\n          player.media.stop = () => {\n            instance.stopVideo();\n          };\n\n          player.media.duration = instance.getDuration();\n          player.media.paused = true;\n\n          // Seeking\n          player.media.currentTime = 0;\n          Object.defineProperty(player.media, 'currentTime', {\n            get() {\n              return Number(instance.getCurrentTime());\n            },\n            set(time) {\n              // If paused and never played, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet).\n              if (player.paused && !player.embed.hasPlayed) {\n                player.embed.mute();\n              }\n\n              // Set seeking state and trigger event\n              player.media.seeking = true;\n              triggerEvent.call(player, player.media, 'seeking');\n\n              // Seek after events sent\n              instance.seekTo(time);\n            },\n          });\n\n          // Playback speed\n          Object.defineProperty(player.media, 'playbackRate', {\n            get() {\n              return instance.getPlaybackRate();\n            },\n            set(input) {\n              instance.setPlaybackRate(input);\n            },\n          });\n\n          // Volume\n          let { volume } = player.config;\n          Object.defineProperty(player.media, 'volume', {\n            get() {\n              return volume;\n            },\n            set(input) {\n              volume = input;\n              instance.setVolume(volume * 100);\n              triggerEvent.call(player, player.media, 'volumechange');\n            },\n          });\n\n          // Muted\n          let { muted } = player.config;\n          Object.defineProperty(player.media, 'muted', {\n            get() {\n              return muted;\n            },\n            set(input) {\n              const toggle = is.boolean(input) ? input : muted;\n              muted = toggle;\n              instance[toggle ? 'mute' : 'unMute']();\n              instance.setVolume(volume * 100);\n              triggerEvent.call(player, player.media, 'volumechange');\n            },\n          });\n\n          // Source\n          Object.defineProperty(player.media, 'currentSrc', {\n            get() {\n              return instance.getVideoUrl();\n            },\n          });\n\n          // Ended\n          Object.defineProperty(player.media, 'ended', {\n            get() {\n              return player.currentTime === player.duration;\n            },\n          });\n\n          // Get available speeds\n          const speeds = instance.getAvailablePlaybackRates();\n          // Filter based on config\n          player.options.speed = speeds.filter((s) => player.config.speed.options.includes(s));\n\n          // Set the tabindex to avoid focus entering iframe\n          if (player.supported.ui && config.customControls) {\n            player.media.setAttribute('tabindex', -1);\n          }\n\n          triggerEvent.call(player, player.media, 'timeupdate');\n          triggerEvent.call(player, player.media, 'durationchange');\n\n          // Reset timer\n          clearInterval(player.timers.buffering);\n\n          // Setup buffering\n          player.timers.buffering = setInterval(() => {\n            // Get loaded % from YouTube\n            player.media.buffered = instance.getVideoLoadedFraction();\n\n            // Trigger progress only when we actually buffer something\n            if (player.media.lastBuffered === null || player.media.lastBuffered < player.media.buffered) {\n              triggerEvent.call(player, player.media, 'progress');\n            }\n\n            // Set last buffer point\n            player.media.lastBuffered = player.media.buffered;\n\n            // Bail if we're at 100%\n            if (player.media.buffered === 1) {\n              clearInterval(player.timers.buffering);\n\n              // Trigger event\n              triggerEvent.call(player, player.media, 'canplaythrough');\n            }\n          }, 200);\n\n          // Rebuild UI\n          if (config.customControls) {\n            setTimeout(() => ui.build.call(player), 50);\n          }\n        },\n        onStateChange(event) {\n          // Get the instance\n          const instance = event.target;\n\n          // Reset timer\n          clearInterval(player.timers.playing);\n\n          const seeked = player.media.seeking && [1, 2].includes(event.data);\n\n          if (seeked) {\n            // Unset seeking and fire seeked event\n            player.media.seeking = false;\n            triggerEvent.call(player, player.media, 'seeked');\n          }\n\n          // Handle events\n          // -1   Unstarted\n          // 0    Ended\n          // 1    Playing\n          // 2    Paused\n          // 3    Buffering\n          // 5    Video cued\n          switch (event.data) {\n            case -1:\n              // Update scrubber\n              triggerEvent.call(player, player.media, 'timeupdate');\n\n              // Get loaded % from YouTube\n              player.media.buffered = instance.getVideoLoadedFraction();\n              triggerEvent.call(player, player.media, 'progress');\n\n              break;\n\n            case 0:\n              assurePlaybackState.call(player, false);\n\n              // YouTube doesn't support loop for a single video, so mimick it.\n              if (player.media.loop) {\n                // YouTube needs a call to `stopVideo` before playing again\n                instance.stopVideo();\n                instance.playVideo();\n              } else {\n                triggerEvent.call(player, player.media, 'ended');\n              }\n\n              break;\n\n            case 1:\n              // Restore paused state (YouTube starts playing on seek if the video hasn't been played yet)\n              if (config.customControls && !player.config.autoplay && player.media.paused && !player.embed.hasPlayed) {\n                player.media.pause();\n              } else {\n                assurePlaybackState.call(player, true);\n\n                triggerEvent.call(player, player.media, 'playing');\n\n                // Poll to get playback progress\n                player.timers.playing = setInterval(() => {\n                  triggerEvent.call(player, player.media, 'timeupdate');\n                }, 50);\n\n                // Check duration again due to YouTube bug\n                // https://github.com/sampotts/plyr/issues/374\n                // https://code.google.com/p/gdata-issues/issues/detail?id=8690\n                if (player.media.duration !== instance.getDuration()) {\n                  player.media.duration = instance.getDuration();\n                  triggerEvent.call(player, player.media, 'durationchange');\n                }\n              }\n\n              break;\n\n            case 2:\n              // Restore audio (YouTube starts playing on seek if the video hasn't been played yet)\n              if (!player.muted) {\n                player.embed.unMute();\n              }\n              assurePlaybackState.call(player, false);\n\n              break;\n\n            case 3:\n              // Trigger waiting event to add loading classes to container as the video buffers.\n              triggerEvent.call(player, player.media, 'waiting');\n\n              break;\n\n            default:\n              break;\n          }\n\n          triggerEvent.call(player, player.elements.container, 'statechange', false, {\n            code: event.data,\n          });\n        },\n      },\n    });\n  },\n};\n\nexport default youtube;\n", "// ==========================================================================\n// Plyr Media\n// ==========================================================================\n\nimport html5 from './html5';\nimport vimeo from './plugins/vimeo';\nimport youtube from './plugins/youtube';\nimport { createElement, toggleClass, wrap } from './utils/elements';\n\nconst media = {\n  // Setup media\n  setup() {\n    // If there's no media, bail\n    if (!this.media) {\n      this.debug.warn('No media element found!');\n      return;\n    }\n\n    // Add type class\n    toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true);\n\n    // Add provider class\n    toggleClass(this.elements.container, this.config.classNames.provider.replace('{0}', this.provider), true);\n\n    // Add video class for embeds\n    // This will require changes if audio embeds are added\n    if (this.isEmbed) {\n      toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true);\n    }\n\n    // Inject the player wrapper\n    if (this.isVideo) {\n      // Create the wrapper div\n      this.elements.wrapper = createElement('div', {\n        class: this.config.classNames.video,\n      });\n\n      // Wrap the video in a container\n      wrap(this.media, this.elements.wrapper);\n\n      // Poster image container\n      this.elements.poster = createElement('div', {\n        class: this.config.classNames.poster,\n      });\n\n      this.elements.wrapper.appendChild(this.elements.poster);\n    }\n\n    if (this.isHTML5) {\n      html5.setup.call(this);\n    } else if (this.isYouTube) {\n      youtube.setup.call(this);\n    } else if (this.isVimeo) {\n      vimeo.setup.call(this);\n    }\n  },\n};\n\nexport default media;\n", "// ==========================================================================\n// Advertisement plugin using Google IMA HTML5 SDK\n// Create an account with our ad partner, vi here:\n// https://www.vi.ai/publisher-video-monetization/\n// ==========================================================================\n\n/* global google */\n\nimport { createElement } from '../utils/elements';\nimport { triggerEvent } from '../utils/events';\nimport i18n from '../utils/i18n';\nimport is from '../utils/is';\nimport loadScript from '../utils/load-script';\nimport { silencePromise } from '../utils/promise';\nimport { formatTime } from '../utils/time';\nimport { buildUrlParams } from '../utils/urls';\n\nconst destroy = (instance) => {\n  // Destroy our adsManager\n  if (instance.manager) {\n    instance.manager.destroy();\n  }\n\n  // Destroy our adsManager\n  if (instance.elements.displayContainer) {\n    instance.elements.displayContainer.destroy();\n  }\n\n  instance.elements.container.remove();\n};\n\nclass Ads {\n  /**\n   * Ads constructor.\n   * @param {Object} player\n   * @return {Ads}\n   */\n  constructor(player) {\n    this.player = player;\n    this.config = player.config.ads;\n    this.playing = false;\n    this.initialized = false;\n    this.elements = {\n      container: null,\n      displayContainer: null,\n    };\n    this.manager = null;\n    this.loader = null;\n    this.cuePoints = null;\n    this.events = {};\n    this.safetyTimer = null;\n    this.countdownTimer = null;\n\n    // Setup a promise to resolve when the IMA manager is ready\n    this.managerPromise = new Promise((resolve, reject) => {\n      // The ad is loaded and ready\n      this.on('loaded', resolve);\n\n      // Ads failed\n      this.on('error', reject);\n    });\n\n    this.load();\n  }\n\n  get enabled() {\n    const { config } = this;\n\n    return (\n      this.player.isHTML5 &&\n      this.player.isVideo &&\n      config.enabled &&\n      (!is.empty(config.publisherId) || is.url(config.tagUrl))\n    );\n  }\n\n  /**\n   * Load the IMA SDK\n   */\n  load = () => {\n    if (!this.enabled) {\n      return;\n    }\n\n    // Check if the Google IMA3 SDK is loaded or load it ourselves\n    if (!is.object(window.google) || !is.object(window.google.ima)) {\n      loadScript(this.player.config.urls.googleIMA.sdk)\n        .then(() => {\n          this.ready();\n        })\n        .catch(() => {\n          // Script failed to load or is blocked\n          this.trigger('error', new Error('Google IMA SDK failed to load'));\n        });\n    } else {\n      this.ready();\n    }\n  };\n\n  /**\n   * Get the ads instance ready\n   */\n  ready = () => {\n    // Double check we're enabled\n    if (!this.enabled) {\n      destroy(this);\n    }\n\n    // Start ticking our safety timer. If the whole advertisement\n    // thing doesn't resolve within our set time; we bail\n    this.startSafetyTimer(12000, 'ready()');\n\n    // Clear the safety timer\n    this.managerPromise.then(() => {\n      this.clearSafetyTimer('onAdsManagerLoaded()');\n    });\n\n    // Set listeners on the Plyr instance\n    this.listeners();\n\n    // Setup the IMA SDK\n    this.setupIMA();\n  };\n\n  // Build the tag URL\n  get tagUrl() {\n    const { config } = this;\n\n    if (is.url(config.tagUrl)) {\n      return config.tagUrl;\n    }\n\n    const params = {\n      AV_PUBLISHERID: '58c25bb0073ef448b1087ad6',\n      AV_CHANNELID: '5a0458dc28a06145e4519d21',\n      AV_URL: window.location.hostname,\n      cb: Date.now(),\n      AV_WIDTH: 640,\n      AV_HEIGHT: 480,\n      AV_CDIM2: config.publisherId,\n    };\n\n    const base = 'https://go.aniview.com/api/adserver6/vast/';\n\n    return `${base}?${buildUrlParams(params)}`;\n  }\n\n  /**\n   * In order for the SDK to display ads for our video, we need to tell it where to put them,\n   * so here we define our ad container. This div is set up to render on top of the video player.\n   * Using the code below, we tell the SDK to render ads within that div. We also provide a\n   * handle to the content video player - the SDK will poll the current time of our player to\n   * properly place mid-rolls. After we create the ad display container, we initialize it. On\n   * mobile devices, this initialization is done as the result of a user action.\n   */\n  setupIMA = () => {\n    // Create the container for our advertisements\n    this.elements.container = createElement('div', {\n      class: this.player.config.classNames.ads,\n    });\n\n    this.player.elements.container.appendChild(this.elements.container);\n\n    // So we can run VPAID2\n    google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED);\n\n    // Set language\n    google.ima.settings.setLocale(this.player.config.ads.language);\n\n    // Set playback for iOS10+\n    google.ima.settings.setDisableCustomPlaybackForIOS10Plus(this.player.config.playsinline);\n\n    // We assume the adContainer is the video container of the plyr element that will house the ads\n    this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container, this.player.media);\n\n    // Create ads loader\n    this.loader = new google.ima.AdsLoader(this.elements.displayContainer);\n\n    // Listen and respond to ads loaded and error events\n    this.loader.addEventListener(\n      google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,\n      (event) => this.onAdsManagerLoaded(event),\n      false,\n    );\n    this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, (error) => this.onAdError(error), false);\n\n    // Request video ads to be pre-loaded\n    this.requestAds();\n  };\n\n  /**\n   * Request advertisements\n   */\n  requestAds = () => {\n    const { container } = this.player.elements;\n\n    try {\n      // Request video ads\n      const request = new google.ima.AdsRequest();\n      request.adTagUrl = this.tagUrl;\n\n      // Specify the linear and nonlinear slot sizes. This helps the SDK\n      // to select the correct creative if multiple are returned\n      request.linearAdSlotWidth = container.offsetWidth;\n      request.linearAdSlotHeight = container.offsetHeight;\n      request.nonLinearAdSlotWidth = container.offsetWidth;\n      request.nonLinearAdSlotHeight = container.offsetHeight;\n\n      // We only overlay ads as we only support video.\n      request.forceNonLinearFullSlot = false;\n\n      // Mute based on current state\n      request.setAdWillPlayMuted(!this.player.muted);\n\n      this.loader.requestAds(request);\n    } catch (error) {\n      this.onAdError(error);\n    }\n  };\n\n  /**\n   * Update the ad countdown\n   * @param {Boolean} start\n   */\n  pollCountdown = (start = false) => {\n    if (!start) {\n      clearInterval(this.countdownTimer);\n      this.elements.container.removeAttribute('data-badge-text');\n      return;\n    }\n\n    const update = () => {\n      const time = formatTime(Math.max(this.manager.getRemainingTime(), 0));\n      const label = `${i18n.get('advertisement', this.player.config)} - ${time}`;\n      this.elements.container.setAttribute('data-badge-text', label);\n    };\n\n    this.countdownTimer = setInterval(update, 100);\n  };\n\n  /**\n   * This method is called whenever the ads are ready inside the AdDisplayContainer\n   * @param {Event} adsManagerLoadedEvent\n   */\n  onAdsManagerLoaded = (event) => {\n    // Load could occur after a source change (race condition)\n    if (!this.enabled) {\n      return;\n    }\n\n    // Get the ads manager\n    const settings = new google.ima.AdsRenderingSettings();\n\n    // Tell the SDK to save and restore content video state on our behalf\n    settings.restoreCustomPlaybackStateOnAdBreakComplete = true;\n    settings.enablePreloading = true;\n\n    // The SDK is polling currentTime on the contentPlayback. And needs a duration\n    // so it can determine when to start the mid- and post-roll\n    this.manager = event.getAdsManager(this.player, settings);\n\n    // Get the cue points for any mid-rolls by filtering out the pre- and post-roll\n    this.cuePoints = this.manager.getCuePoints();\n\n    // Add listeners to the required events\n    // Advertisement error events\n    this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, (error) => this.onAdError(error));\n\n    // Advertisement regular events\n    Object.keys(google.ima.AdEvent.Type).forEach((type) => {\n      this.manager.addEventListener(google.ima.AdEvent.Type[type], (e) => this.onAdEvent(e));\n    });\n\n    // Resolve our adsManager\n    this.trigger('loaded');\n  };\n\n  addCuePoints = () => {\n    // Add advertisement cue's within the time line if available\n    if (!is.empty(this.cuePoints)) {\n      this.cuePoints.forEach((cuePoint) => {\n        if (cuePoint !== 0 && cuePoint !== -1 && cuePoint < this.player.duration) {\n          const seekElement = this.player.elements.progress;\n\n          if (is.element(seekElement)) {\n            const cuePercentage = (100 / this.player.duration) * cuePoint;\n            const cue = createElement('span', {\n              class: this.player.config.classNames.cues,\n            });\n\n            cue.style.left = `${cuePercentage.toString()}%`;\n            seekElement.appendChild(cue);\n          }\n        }\n      });\n    }\n  };\n\n  /**\n   * This is where all the event handling takes place. Retrieve the ad from the event. Some\n   * events (e.g. ALL_ADS_COMPLETED) don't have the ad object associated\n   * https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis#ima.AdEvent.Type\n   * @param {Event} event\n   */\n  onAdEvent = (event) => {\n    const { container } = this.player.elements;\n    // Retrieve the ad from the event. Some events (e.g. ALL_ADS_COMPLETED)\n    // don't have ad object associated\n    const ad = event.getAd();\n    const adData = event.getAdData();\n\n    // Proxy event\n    const dispatchEvent = (type) => {\n      triggerEvent.call(this.player, this.player.media, `ads${type.replace(/_/g, '').toLowerCase()}`);\n    };\n\n    // Bubble the event\n    dispatchEvent(event.type);\n\n    switch (event.type) {\n      case google.ima.AdEvent.Type.LOADED:\n        // This is the first event sent for an ad - it is possible to determine whether the\n        // ad is a video ad or an overlay\n        this.trigger('loaded');\n\n        // Start countdown\n        this.pollCountdown(true);\n\n        if (!ad.isLinear()) {\n          // Position AdDisplayContainer correctly for overlay\n          ad.width = container.offsetWidth;\n          ad.height = container.offsetHeight;\n        }\n\n        // console.info('Ad type: ' + event.getAd().getAdPodInfo().getPodIndex());\n        // console.info('Ad time: ' + event.getAd().getAdPodInfo().getTimeOffset());\n\n        break;\n\n      case google.ima.AdEvent.Type.STARTED:\n        // Set volume to match player\n        this.manager.setVolume(this.player.volume);\n\n        break;\n\n      case google.ima.AdEvent.Type.ALL_ADS_COMPLETED:\n        // All ads for the current videos are done. We can now request new advertisements\n        // in case the video is re-played\n\n        // TODO: Example for what happens when a next video in a playlist would be loaded.\n        // So here we load a new video when all ads are done.\n        // Then we load new ads within a new adsManager. When the video\n        // Is started - after - the ads are loaded, then we get ads.\n        // You can also easily test cancelling and reloading by running\n        // player.ads.cancel() and player.ads.play from the console I guess.\n        // this.player.source = {\n        //     type: 'video',\n        //     title: 'View From A Blue Moon',\n        //     sources: [{\n        //         src:\n        // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.mp4', type:\n        // 'video/mp4', }], poster:\n        // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg', tracks:\n        // [ { kind: 'captions', label: 'English', srclang: 'en', src:\n        // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt',\n        // default: true, }, { kind: 'captions', label: 'French', srclang: 'fr', src:\n        // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt', }, ],\n        // };\n\n        // TODO: So there is still this thing where a video should only be allowed to start\n        // playing when the IMA SDK is ready or has failed\n\n        if (this.player.ended) {\n          this.loadAds();\n        } else {\n          // The SDK won't allow new ads to be called without receiving a contentComplete()\n          this.loader.contentComplete();\n        }\n\n        break;\n\n      case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:\n        // This event indicates the ad has started - the video player can adjust the UI,\n        // for example display a pause button and remaining time. Fired when content should\n        // be paused. This usually happens right before an ad is about to cover the content\n\n        this.pauseContent();\n\n        break;\n\n      case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED:\n        // This event indicates the ad has finished - the video player can perform\n        // appropriate UI actions, such as removing the timer for remaining time detection.\n        // Fired when content should be resumed. This usually happens when an ad finishes\n        // or collapses\n\n        this.pollCountdown();\n\n        this.resumeContent();\n\n        break;\n\n      case google.ima.AdEvent.Type.LOG:\n        if (adData.adError) {\n          this.player.debug.warn(`Non-fatal ad error: ${adData.adError.getMessage()}`);\n        }\n\n        break;\n\n      default:\n        break;\n    }\n  };\n\n  /**\n   * Any ad error handling comes through here\n   * @param {Event} event\n   */\n  onAdError = (event) => {\n    this.cancel();\n    this.player.debug.warn('Ads error', event);\n  };\n\n  /**\n   * Setup hooks for Plyr and window events. This ensures\n   * the mid- and post-roll launch at the correct time. And\n   * resize the advertisement when the player resizes\n   */\n  listeners = () => {\n    const { container } = this.player.elements;\n    let time;\n\n    this.player.on('canplay', () => {\n      this.addCuePoints();\n    });\n\n    this.player.on('ended', () => {\n      this.loader.contentComplete();\n    });\n\n    this.player.on('timeupdate', () => {\n      time = this.player.currentTime;\n    });\n\n    this.player.on('seeked', () => {\n      const seekedTime = this.player.currentTime;\n\n      if (is.empty(this.cuePoints)) {\n        return;\n      }\n\n      this.cuePoints.forEach((cuePoint, index) => {\n        if (time < cuePoint && cuePoint < seekedTime) {\n          this.manager.discardAdBreak();\n          this.cuePoints.splice(index, 1);\n        }\n      });\n    });\n\n    // Listen to the resizing of the window. And resize ad accordingly\n    // TODO: eventually implement ResizeObserver\n    window.addEventListener('resize', () => {\n      if (this.manager) {\n        this.manager.resize(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);\n      }\n    });\n  };\n\n  /**\n   * Initialize the adsManager and start playing advertisements\n   */\n  play = () => {\n    const { container } = this.player.elements;\n\n    if (!this.managerPromise) {\n      this.resumeContent();\n    }\n\n    // Play the requested advertisement whenever the adsManager is ready\n    this.managerPromise\n      .then(() => {\n        // Set volume to match player\n        this.manager.setVolume(this.player.volume);\n\n        // Initialize the container. Must be done via a user action on mobile devices\n        this.elements.displayContainer.initialize();\n\n        try {\n          if (!this.initialized) {\n            // Initialize the ads manager. Ad rules playlist will start at this time\n            this.manager.init(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);\n\n            // Call play to start showing the ad. Single video and overlay ads will\n            // start at this time; the call will be ignored for ad rules\n            this.manager.start();\n          }\n\n          this.initialized = true;\n        } catch (adError) {\n          // An error may be thrown if there was a problem with the\n          // VAST response\n          this.onAdError(adError);\n        }\n      })\n      .catch(() => {});\n  };\n\n  /**\n   * Resume our video\n   */\n  resumeContent = () => {\n    // Hide the advertisement container\n    this.elements.container.style.zIndex = '';\n\n    // Ad is stopped\n    this.playing = false;\n\n    // Play video\n    silencePromise(this.player.media.play());\n  };\n\n  /**\n   * Pause our video\n   */\n  pauseContent = () => {\n    // Show the advertisement container\n    this.elements.container.style.zIndex = 3;\n\n    // Ad is playing\n    this.playing = true;\n\n    // Pause our video.\n    this.player.media.pause();\n  };\n\n  /**\n   * Destroy the adsManager so we can grab new ads after this. If we don't then we're not\n   * allowed to call new ads based on google policies, as they interpret this as an accidental\n   * video requests. https://developers.google.com/interactive-\n   * media-ads/docs/sdks/android/faq#8\n   */\n  cancel = () => {\n    // Pause our video\n    if (this.initialized) {\n      this.resumeContent();\n    }\n\n    // Tell our instance that we're done for now\n    this.trigger('error');\n\n    // Re-create our adsManager\n    this.loadAds();\n  };\n\n  /**\n   * Re-create our adsManager\n   */\n  loadAds = () => {\n    // Tell our adsManager to go bye bye\n    this.managerPromise\n      .then(() => {\n        // Destroy our adsManager\n        if (this.manager) {\n          this.manager.destroy();\n        }\n\n        // Re-set our adsManager promises\n        this.managerPromise = new Promise((resolve) => {\n          this.on('loaded', resolve);\n          this.player.debug.log(this.manager);\n        });\n        // Now that the manager has been destroyed set it to also be un-initialized\n        this.initialized = false;\n\n        // Now request some new advertisements\n        this.requestAds();\n      })\n      .catch(() => {});\n  };\n\n  /**\n   * Handles callbacks after an ad event was invoked\n   * @param {String} event - Event type\n   */\n  trigger = (event, ...args) => {\n    const handlers = this.events[event];\n\n    if (is.array(handlers)) {\n      handlers.forEach((handler) => {\n        if (is.function(handler)) {\n          handler.apply(this, args);\n        }\n      });\n    }\n  };\n\n  /**\n   * Add event listeners\n   * @param {String} event - Event type\n   * @param {Function} callback - Callback for when event occurs\n   * @return {Ads}\n   */\n  on = (event, callback) => {\n    if (!is.array(this.events[event])) {\n      this.events[event] = [];\n    }\n\n    this.events[event].push(callback);\n\n    return this;\n  };\n\n  /**\n   * Setup a safety timer for when the ad network doesn't respond for whatever reason.\n   * The advertisement has 12 seconds to get its things together. We stop this timer when the\n   * advertisement is playing, or when a user action is required to start, then we clear the\n   * timer on ad ready\n   * @param {Number} time\n   * @param {String} from\n   */\n  startSafetyTimer = (time, from) => {\n    this.player.debug.log(`Safety timer invoked from: ${from}`);\n\n    this.safetyTimer = setTimeout(() => {\n      this.cancel();\n      this.clearSafetyTimer('startSafetyTimer()');\n    }, time);\n  };\n\n  /**\n   * Clear our safety timer(s)\n   * @param {String} from\n   */\n  clearSafetyTimer = (from) => {\n    if (!is.nullOrUndefined(this.safetyTimer)) {\n      this.player.debug.log(`Safety timer cleared from: ${from}`);\n\n      clearTimeout(this.safetyTimer);\n      this.safetyTimer = null;\n    }\n  };\n}\n\nexport default Ads;\n", "import { createElement } from '../utils/elements';\nimport { once } from '../utils/events';\nimport fetch from '../utils/fetch';\nimport is from '../utils/is';\nimport { formatTime } from '../utils/time';\n\n// Arg: vttDataString example: \"WEBVTT\\n\\n1\\n00:00:05.000 --> 00:00:10.000\\n1080p-00001.jpg\"\nconst parseVtt = (vttDataString) => {\n  const processedList = [];\n  const frames = vttDataString.split(/\\r\\n\\r\\n|\\n\\n|\\r\\r/);\n\n  frames.forEach((frame) => {\n    const result = {};\n    const lines = frame.split(/\\r\\n|\\n|\\r/);\n\n    lines.forEach((line) => {\n      if (!is.number(result.startTime)) {\n        // The line with start and end times on it is the first line of interest\n        const matchTimes = line.match(\n          /([0-9]{2})?:?([0-9]{2}):([0-9]{2}).([0-9]{2,3})( ?--> ?)([0-9]{2})?:?([0-9]{2}):([0-9]{2}).([0-9]{2,3})/,\n        ); // Note that this currently ignores caption formatting directives that are optionally on the end of this line - fine for non-captions VTT\n\n        if (matchTimes) {\n          result.startTime =\n            Number(matchTimes[1] || 0) * 60 * 60 +\n            Number(matchTimes[2]) * 60 +\n            Number(matchTimes[3]) +\n            Number(`0.${matchTimes[4]}`);\n          result.endTime =\n            Number(matchTimes[6] || 0) * 60 * 60 +\n            Number(matchTimes[7]) * 60 +\n            Number(matchTimes[8]) +\n            Number(`0.${matchTimes[9]}`);\n        }\n      } else if (!is.empty(line.trim()) && is.empty(result.text)) {\n        // If we already have the startTime, then we're definitely up to the text line(s)\n        const lineSplit = line.trim().split('#xywh=');\n        [result.text] = lineSplit;\n\n        // If there's content in lineSplit[1], then we have sprites. If not, then it's just one frame per image\n        if (lineSplit[1]) {\n          [result.x, result.y, result.w, result.h] = lineSplit[1].split(',');\n        }\n      }\n    });\n\n    if (result.text) {\n      processedList.push(result);\n    }\n  });\n\n  return processedList;\n};\n\n/**\n * Preview thumbnails for seek hover and scrubbing\n * Seeking: Hover over the seek bar (desktop only): shows a small preview container above the seek bar\n * Scrubbing: Click and drag the seek bar (desktop and mobile): shows the preview image over the entire video, as if the video is scrubbing at very high speed\n *\n * Notes:\n * - Thumbs are set via JS settings on Plyr init, not HTML5 'track' property. Using the track property would be a bit gross, because it doesn't support custom 'kinds'. kind=metadata might be used for something else, and we want to allow multiple thumbnails tracks. Tracks must have a unique combination of 'kind' and 'label'. We would have to do something like kind=metadata,label=thumbnails1 / kind=metadata,label=thumbnails2. Square peg, round hole\n * - VTT info: the image URL is relative to the VTT, not the current document. But if the url starts with a slash, it will naturally be relative to the current domain. https://support.jwplayer.com/articles/how-to-add-preview-thumbnails\n * - This implementation uses multiple separate img elements. Other implementations use background-image on one element. This would be nice and simple, but Firefox and Safari have flickering issues with replacing backgrounds of larger images. It seems that YouTube perhaps only avoids this because they don't have the option for high-res previews (even the fullscreen ones, when mousedown/seeking). Images appear over the top of each other, and previous ones are discarded once the new ones have been rendered\n */\n\nconst fitRatio = (ratio, outer) => {\n  const targetRatio = outer.width / outer.height;\n  const result = {};\n  if (ratio > targetRatio) {\n    result.width = outer.width;\n    result.height = (1 / ratio) * outer.width;\n  } else {\n    result.height = outer.height;\n    result.width = ratio * outer.height;\n  }\n\n  return result;\n};\n\nclass PreviewThumbnails {\n  /**\n   * PreviewThumbnails constructor.\n   * @param {Plyr} player\n   * @return {PreviewThumbnails}\n   */\n  constructor(player) {\n    this.player = player;\n    this.thumbnails = [];\n    this.loaded = false;\n    this.lastMouseMoveTime = Date.now();\n    this.mouseDown = false;\n    this.loadedImages = [];\n\n    this.elements = {\n      thumb: {},\n      scrubbing: {},\n    };\n\n    this.load();\n  }\n\n  get enabled() {\n    return this.player.isHTML5 && this.player.isVideo && this.player.config.previewThumbnails.enabled;\n  }\n\n  load = () => {\n    // Toggle the regular seek tooltip\n    if (this.player.elements.display.seekTooltip) {\n      this.player.elements.display.seekTooltip.hidden = this.enabled;\n    }\n\n    if (!this.enabled) {\n      return;\n    }\n\n    this.getThumbnails().then(() => {\n      if (!this.enabled) {\n        return;\n      }\n\n      // Render DOM elements\n      this.render();\n\n      // Check to see if thumb container size was specified manually in CSS\n      this.determineContainerAutoSizing();\n\n      this.loaded = true;\n    });\n  };\n\n  // Download VTT files and parse them\n  getThumbnails = () => {\n    return new Promise((resolve) => {\n      const { src } = this.player.config.previewThumbnails;\n\n      if (is.empty(src)) {\n        throw new Error('Missing previewThumbnails.src config attribute');\n      }\n\n      // Resolve promise\n      const sortAndResolve = () => {\n        // Sort smallest to biggest (e.g., [120p, 480p, 1080p])\n        this.thumbnails.sort((x, y) => x.height - y.height);\n\n        this.player.debug.log('Preview thumbnails', this.thumbnails);\n\n        resolve();\n      };\n\n      // Via callback()\n      if (is.function(src)) {\n        src((thumbnails) => {\n          this.thumbnails = thumbnails;\n          sortAndResolve();\n        });\n      }\n      // VTT urls\n      else {\n        // If string, convert into single-element list\n        const urls = is.string(src) ? [src] : src;\n        // Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails\n        const promises = urls.map((u) => this.getThumbnail(u));\n        // Resolve\n        Promise.all(promises).then(sortAndResolve);\n      }\n    });\n  };\n\n  // Process individual VTT file\n  getThumbnail = (url) => {\n    return new Promise((resolve) => {\n      fetch(url).then((response) => {\n        const thumbnail = {\n          frames: parseVtt(response),\n          height: null,\n          urlPrefix: '',\n        };\n\n        // If the URLs don't start with '/', then we need to set their relative path to be the location of the VTT file\n        // If the URLs do start with '/', then they obviously don't need a prefix, so it will remain blank\n        // If the thumbnail URLs start with with none of '/', 'http://' or 'https://', then we need to set their relative path to be the location of the VTT file\n        if (\n          !thumbnail.frames[0].text.startsWith('/') &&\n          !thumbnail.frames[0].text.startsWith('http://') &&\n          !thumbnail.frames[0].text.startsWith('https://')\n        ) {\n          thumbnail.urlPrefix = url.substring(0, url.lastIndexOf('/') + 1);\n        }\n\n        // Download the first frame, so that we can determine/set the height of this thumbnailsDef\n        const tempImage = new Image();\n\n        tempImage.onload = () => {\n          thumbnail.height = tempImage.naturalHeight;\n          thumbnail.width = tempImage.naturalWidth;\n\n          this.thumbnails.push(thumbnail);\n\n          resolve();\n        };\n\n        tempImage.src = thumbnail.urlPrefix + thumbnail.frames[0].text;\n      });\n    });\n  };\n\n  startMove = (event) => {\n    if (!this.loaded) {\n      return;\n    }\n\n    if (!is.event(event) || !['touchmove', 'mousemove'].includes(event.type)) {\n      return;\n    }\n\n    // Wait until media has a duration\n    if (!this.player.media.duration) {\n      return;\n    }\n\n    if (event.type === 'touchmove') {\n      // Calculate seek hover position as approx video seconds\n      this.seekTime = this.player.media.duration * (this.player.elements.inputs.seek.value / 100);\n    } else {\n      // Calculate seek hover position as approx video seconds\n      const clientRect = this.player.elements.progress.getBoundingClientRect();\n      const percentage = (100 / clientRect.width) * (event.pageX - clientRect.left);\n      this.seekTime = this.player.media.duration * (percentage / 100);\n\n      if (this.seekTime < 0) {\n        // The mousemove fires for 10+px out to the left\n        this.seekTime = 0;\n      }\n\n      if (this.seekTime > this.player.media.duration - 1) {\n        // Took 1 second off the duration for safety, because different players can disagree on the real duration of a video\n        this.seekTime = this.player.media.duration - 1;\n      }\n\n      this.mousePosX = event.pageX;\n\n      // Set time text inside image container\n      this.elements.thumb.time.innerText = formatTime(this.seekTime);\n    }\n\n    // Download and show image\n    this.showImageAtCurrentTime();\n  };\n\n  endMove = () => {\n    this.toggleThumbContainer(false, true);\n  };\n\n  startScrubbing = (event) => {\n    // Only act on left mouse button (0), or touch device (event.button does not exist or is false)\n    if (is.nullOrUndefined(event.button) || event.button === false || event.button === 0) {\n      this.mouseDown = true;\n\n      // Wait until media has a duration\n      if (this.player.media.duration) {\n        this.toggleScrubbingContainer(true);\n        this.toggleThumbContainer(false, true);\n\n        // Download and show image\n        this.showImageAtCurrentTime();\n      }\n    }\n  };\n\n  endScrubbing = () => {\n    this.mouseDown = false;\n\n    // Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview\n    if (Math.ceil(this.lastTime) === Math.ceil(this.player.media.currentTime)) {\n      // The video was already seeked/loaded at the chosen time - hide immediately\n      this.toggleScrubbingContainer(false);\n    } else {\n      // The video hasn't seeked yet. Wait for that\n      once.call(this.player, this.player.media, 'timeupdate', () => {\n        // Re-check mousedown - we might have already started scrubbing again\n        if (!this.mouseDown) {\n          this.toggleScrubbingContainer(false);\n        }\n      });\n    }\n  };\n\n  /**\n   * Setup hooks for Plyr and window events\n   */\n  listeners = () => {\n    // Hide thumbnail preview - on mouse click, mouse leave (in listeners.js for now), and video play/seek. All four are required, e.g., for buffering\n    this.player.on('play', () => {\n      this.toggleThumbContainer(false, true);\n    });\n\n    this.player.on('seeked', () => {\n      this.toggleThumbContainer(false);\n    });\n\n    this.player.on('timeupdate', () => {\n      this.lastTime = this.player.media.currentTime;\n    });\n  };\n\n  /**\n   * Create HTML elements for image containers\n   */\n  render = () => {\n    // Create HTML element: plyr__preview-thumbnail-container\n    this.elements.thumb.container = createElement('div', {\n      class: this.player.config.classNames.previewThumbnails.thumbContainer,\n    });\n\n    // Wrapper for the image for styling\n    this.elements.thumb.imageContainer = createElement('div', {\n      class: this.player.config.classNames.previewThumbnails.imageContainer,\n    });\n    this.elements.thumb.container.appendChild(this.elements.thumb.imageContainer);\n\n    // Create HTML element, parent+span: time text (e.g., 01:32:00)\n    const timeContainer = createElement('div', {\n      class: this.player.config.classNames.previewThumbnails.timeContainer,\n    });\n\n    this.elements.thumb.time = createElement('span', {}, '00:00');\n    timeContainer.appendChild(this.elements.thumb.time);\n\n    this.elements.thumb.container.appendChild(timeContainer);\n\n    // Inject the whole thumb\n    if (is.element(this.player.elements.progress)) {\n      this.player.elements.progress.appendChild(this.elements.thumb.container);\n    }\n\n    // Create HTML element: plyr__preview-scrubbing-container\n    this.elements.scrubbing.container = createElement('div', {\n      class: this.player.config.classNames.previewThumbnails.scrubbingContainer,\n    });\n\n    this.player.elements.wrapper.appendChild(this.elements.scrubbing.container);\n  };\n\n  destroy = () => {\n    if (this.elements.thumb.container) {\n      this.elements.thumb.container.remove();\n    }\n    if (this.elements.scrubbing.container) {\n      this.elements.scrubbing.container.remove();\n    }\n  };\n\n  showImageAtCurrentTime = () => {\n    if (this.mouseDown) {\n      this.setScrubbingContainerSize();\n    } else {\n      this.setThumbContainerSizeAndPos();\n    }\n\n    // Find the desired thumbnail index\n    // TODO: Handle a video longer than the thumbs where thumbNum is null\n    const thumbNum = this.thumbnails[0].frames.findIndex(\n      (frame) => this.seekTime >= frame.startTime && this.seekTime <= frame.endTime,\n    );\n    const hasThumb = thumbNum >= 0;\n    let qualityIndex = 0;\n\n    // Show the thumb container if we're not scrubbing\n    if (!this.mouseDown) {\n      this.toggleThumbContainer(hasThumb);\n    }\n\n    // No matching thumb found\n    if (!hasThumb) {\n      return;\n    }\n\n    // Check to see if we've already downloaded higher quality versions of this image\n    this.thumbnails.forEach((thumbnail, index) => {\n      if (this.loadedImages.includes(thumbnail.frames[thumbNum].text)) {\n        qualityIndex = index;\n      }\n    });\n\n    // Only proceed if either thumbnum or thumbfilename has changed\n    if (thumbNum !== this.showingThumb) {\n      this.showingThumb = thumbNum;\n      this.loadImage(qualityIndex);\n    }\n  };\n\n  // Show the image that's currently specified in this.showingThumb\n  loadImage = (qualityIndex = 0) => {\n    const thumbNum = this.showingThumb;\n    const thumbnail = this.thumbnails[qualityIndex];\n    const { urlPrefix } = thumbnail;\n    const frame = thumbnail.frames[thumbNum];\n    const thumbFilename = thumbnail.frames[thumbNum].text;\n    const thumbUrl = urlPrefix + thumbFilename;\n\n    if (!this.currentImageElement || this.currentImageElement.dataset.filename !== thumbFilename) {\n      // If we're already loading a previous image, remove its onload handler - we don't want it to load after this one\n      // Only do this if not using sprites. Without sprites we really want to show as many images as possible, as a best-effort\n      if (this.loadingImage && this.usingSprites) {\n        this.loadingImage.onload = null;\n      }\n\n      // We're building and adding a new image. In other implementations of similar functionality (YouTube), background image\n      // is instead used. But this causes issues with larger images in Firefox and Safari - switching between background\n      // images causes a flicker. Putting a new image over the top does not\n      const previewImage = new Image();\n      previewImage.src = thumbUrl;\n      previewImage.dataset.index = thumbNum;\n      previewImage.dataset.filename = thumbFilename;\n      this.showingThumbFilename = thumbFilename;\n\n      this.player.debug.log(`Loading image: ${thumbUrl}`);\n\n      // For some reason, passing the named function directly causes it to execute immediately. So I've wrapped it in an anonymous function...\n      previewImage.onload = () => this.showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, true);\n      this.loadingImage = previewImage;\n      this.removeOldImages(previewImage);\n    } else {\n      // Update the existing image\n      this.showImage(this.currentImageElement, frame, qualityIndex, thumbNum, thumbFilename, false);\n      this.currentImageElement.dataset.index = thumbNum;\n      this.removeOldImages(this.currentImageElement);\n    }\n  };\n\n  showImage = (previewImage, frame, qualityIndex, thumbNum, thumbFilename, newImage = true) => {\n    this.player.debug.log(\n      `Showing thumb: ${thumbFilename}. num: ${thumbNum}. qual: ${qualityIndex}. newimg: ${newImage}`,\n    );\n    this.setImageSizeAndOffset(previewImage, frame);\n\n    if (newImage) {\n      this.currentImageContainer.appendChild(previewImage);\n      this.currentImageElement = previewImage;\n\n      if (!this.loadedImages.includes(thumbFilename)) {\n        this.loadedImages.push(thumbFilename);\n      }\n    }\n\n    // Preload images before and after the current one\n    // Show higher quality of the same frame\n    // Each step here has a short time delay, and only continues if still hovering/seeking the same spot. This is to protect slow connections from overloading\n    this.preloadNearby(thumbNum, true)\n      .then(this.preloadNearby(thumbNum, false))\n      .then(this.getHigherQuality(qualityIndex, previewImage, frame, thumbFilename));\n  };\n\n  // Remove all preview images that aren't the designated current image\n  removeOldImages = (currentImage) => {\n    // Get a list of all images, convert it from a DOM list to an array\n    Array.from(this.currentImageContainer.children).forEach((image) => {\n      if (image.tagName.toLowerCase() !== 'img') {\n        return;\n      }\n\n      const removeDelay = this.usingSprites ? 500 : 1000;\n\n      if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) {\n        // Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients\n        // First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function\n        // eslint-disable-next-line no-param-reassign\n        image.dataset.deleting = true;\n\n        // This has to be set before the timeout - to prevent issues switching between hover and scrub\n        const { currentImageContainer } = this;\n\n        setTimeout(() => {\n          currentImageContainer.removeChild(image);\n          this.player.debug.log(`Removing thumb: ${image.dataset.filename}`);\n        }, removeDelay);\n      }\n    });\n  };\n\n  // Preload images before and after the current one. Only if the user is still hovering/seeking the same frame\n  // This will only preload the lowest quality\n  preloadNearby = (thumbNum, forward = true) => {\n    return new Promise((resolve) => {\n      setTimeout(() => {\n        const oldThumbFilename = this.thumbnails[0].frames[thumbNum].text;\n\n        if (this.showingThumbFilename === oldThumbFilename) {\n          // Find the nearest thumbs with different filenames. Sometimes it'll be the next index, but in the case of sprites, it might be 100+ away\n          let thumbnailsClone;\n          if (forward) {\n            thumbnailsClone = this.thumbnails[0].frames.slice(thumbNum);\n          } else {\n            thumbnailsClone = this.thumbnails[0].frames.slice(0, thumbNum).reverse();\n          }\n\n          let foundOne = false;\n\n          thumbnailsClone.forEach((frame) => {\n            const newThumbFilename = frame.text;\n\n            if (newThumbFilename !== oldThumbFilename) {\n              // Found one with a different filename. Make sure it hasn't already been loaded on this page visit\n              if (!this.loadedImages.includes(newThumbFilename)) {\n                foundOne = true;\n                this.player.debug.log(`Preloading thumb filename: ${newThumbFilename}`);\n\n                const { urlPrefix } = this.thumbnails[0];\n                const thumbURL = urlPrefix + newThumbFilename;\n                const previewImage = new Image();\n                previewImage.src = thumbURL;\n                previewImage.onload = () => {\n                  this.player.debug.log(`Preloaded thumb filename: ${newThumbFilename}`);\n                  if (!this.loadedImages.includes(newThumbFilename)) this.loadedImages.push(newThumbFilename);\n\n                  // We don't resolve until the thumb is loaded\n                  resolve();\n                };\n              }\n            }\n          });\n\n          // If there are none to preload then we want to resolve immediately\n          if (!foundOne) {\n            resolve();\n          }\n        }\n      }, 300);\n    });\n  };\n\n  // If user has been hovering current image for half a second, look for a higher quality one\n  getHigherQuality = (currentQualityIndex, previewImage, frame, thumbFilename) => {\n    if (currentQualityIndex < this.thumbnails.length - 1) {\n      // Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container\n      let previewImageHeight = previewImage.naturalHeight;\n\n      if (this.usingSprites) {\n        previewImageHeight = frame.h;\n      }\n\n      if (previewImageHeight < this.thumbContainerHeight) {\n        // Recurse back to the loadImage function - show a higher quality one, but only if the viewer is on this frame for a while\n        setTimeout(() => {\n          // Make sure the mouse hasn't already moved on and started hovering at another image\n          if (this.showingThumbFilename === thumbFilename) {\n            this.player.debug.log(`Showing higher quality thumb for: ${thumbFilename}`);\n            this.loadImage(currentQualityIndex + 1);\n          }\n        }, 300);\n      }\n    }\n  };\n\n  get currentImageContainer() {\n    if (this.mouseDown) {\n      return this.elements.scrubbing.container;\n    }\n\n    return this.elements.thumb.imageContainer;\n  }\n\n  get usingSprites() {\n    return Object.keys(this.thumbnails[0].frames[0]).includes('w');\n  }\n\n  get thumbAspectRatio() {\n    if (this.usingSprites) {\n      return this.thumbnails[0].frames[0].w / this.thumbnails[0].frames[0].h;\n    }\n\n    return this.thumbnails[0].width / this.thumbnails[0].height;\n  }\n\n  get thumbContainerHeight() {\n    if (this.mouseDown) {\n      const { height } = fitRatio(this.thumbAspectRatio, {\n        width: this.player.media.clientWidth,\n        height: this.player.media.clientHeight,\n      });\n      return height;\n    }\n\n    // If css is used this needs to return the css height for sprites to work (see setImageSizeAndOffset)\n    if (this.sizeSpecifiedInCSS) {\n      return this.elements.thumb.imageContainer.clientHeight;\n    }\n\n    return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio / 4);\n  }\n\n  get currentImageElement() {\n    if (this.mouseDown) {\n      return this.currentScrubbingImageElement;\n    }\n\n    return this.currentThumbnailImageElement;\n  }\n\n  set currentImageElement(element) {\n    if (this.mouseDown) {\n      this.currentScrubbingImageElement = element;\n    } else {\n      this.currentThumbnailImageElement = element;\n    }\n  }\n\n  toggleThumbContainer = (toggle = false, clearShowing = false) => {\n    const className = this.player.config.classNames.previewThumbnails.thumbContainerShown;\n    this.elements.thumb.container.classList.toggle(className, toggle);\n\n    if (!toggle && clearShowing) {\n      this.showingThumb = null;\n      this.showingThumbFilename = null;\n    }\n  };\n\n  toggleScrubbingContainer = (toggle = false) => {\n    const className = this.player.config.classNames.previewThumbnails.scrubbingContainerShown;\n    this.elements.scrubbing.container.classList.toggle(className, toggle);\n\n    if (!toggle) {\n      this.showingThumb = null;\n      this.showingThumbFilename = null;\n    }\n  };\n\n  determineContainerAutoSizing = () => {\n    if (this.elements.thumb.imageContainer.clientHeight > 20 || this.elements.thumb.imageContainer.clientWidth > 20) {\n      // This will prevent auto sizing in this.setThumbContainerSizeAndPos()\n      this.sizeSpecifiedInCSS = true;\n    }\n  };\n\n  // Set the size to be about a quarter of the size of video. Unless option dynamicSize === false, in which case it needs to be set in CSS\n  setThumbContainerSizeAndPos = () => {\n    if (!this.sizeSpecifiedInCSS) {\n      const thumbWidth = Math.floor(this.thumbContainerHeight * this.thumbAspectRatio);\n      this.elements.thumb.imageContainer.style.height = `${this.thumbContainerHeight}px`;\n      this.elements.thumb.imageContainer.style.width = `${thumbWidth}px`;\n    } else if (\n      this.elements.thumb.imageContainer.clientHeight > 20 &&\n      this.elements.thumb.imageContainer.clientWidth < 20\n    ) {\n      const thumbWidth = Math.floor(this.elements.thumb.imageContainer.clientHeight * this.thumbAspectRatio);\n      this.elements.thumb.imageContainer.style.width = `${thumbWidth}px`;\n    } else if (\n      this.elements.thumb.imageContainer.clientHeight < 20 &&\n      this.elements.thumb.imageContainer.clientWidth > 20\n    ) {\n      const thumbHeight = Math.floor(this.elements.thumb.imageContainer.clientWidth / this.thumbAspectRatio);\n      this.elements.thumb.imageContainer.style.height = `${thumbHeight}px`;\n    }\n\n    this.setThumbContainerPos();\n  };\n\n  setThumbContainerPos = () => {\n    const seekbarRect = this.player.elements.progress.getBoundingClientRect();\n    const plyrRect = this.player.elements.container.getBoundingClientRect();\n    const { container } = this.elements.thumb;\n    // Find the lowest and highest desired left-position, so we don't slide out the side of the video container\n    const minVal = plyrRect.left - seekbarRect.left + 10;\n    const maxVal = plyrRect.right - seekbarRect.left - container.clientWidth - 10;\n    // Set preview container position to: mousepos, minus seekbar.left, minus half of previewContainer.clientWidth\n    let previewPos = this.mousePosX - seekbarRect.left - container.clientWidth / 2;\n\n    if (previewPos < minVal) {\n      previewPos = minVal;\n    }\n\n    if (previewPos > maxVal) {\n      previewPos = maxVal;\n    }\n\n    container.style.left = `${previewPos}px`;\n  };\n\n  // Can't use 100% width, in case the video is a different aspect ratio to the video container\n  setScrubbingContainerSize = () => {\n    const { width, height } = fitRatio(this.thumbAspectRatio, {\n      width: this.player.media.clientWidth,\n      height: this.player.media.clientHeight,\n    });\n    this.elements.scrubbing.container.style.width = `${width}px`;\n    this.elements.scrubbing.container.style.height = `${height}px`;\n  };\n\n  // Sprites need to be offset to the correct location\n  setImageSizeAndOffset = (previewImage, frame) => {\n    if (!this.usingSprites) {\n      return;\n    }\n\n    // Find difference between height and preview container height\n    const multiplier = this.thumbContainerHeight / frame.h;\n\n    // eslint-disable-next-line no-param-reassign\n    previewImage.style.height = `${previewImage.naturalHeight * multiplier}px`;\n    // eslint-disable-next-line no-param-reassign\n    previewImage.style.width = `${previewImage.naturalWidth * multiplier}px`;\n    // eslint-disable-next-line no-param-reassign\n    previewImage.style.left = `-${frame.x * multiplier}px`;\n    // eslint-disable-next-line no-param-reassign\n    previewImage.style.top = `-${frame.y * multiplier}px`;\n  };\n}\n\nexport default PreviewThumbnails;\n", "// ==========================================================================\n// Plyr source update\n// ==========================================================================\n\nimport { providers } from './config/types';\nimport html5 from './html5';\nimport media from './media';\nimport PreviewThumbnails from './plugins/preview-thumbnails';\nimport support from './support';\nimport ui from './ui';\nimport { createElement, insertElement, removeElement } from './utils/elements';\nimport is from './utils/is';\nimport { getDeep } from './utils/objects';\n\nconst source = {\n  // Add elements to HTML5 media (source, tracks, etc)\n  insertElements(type, attributes) {\n    if (is.string(attributes)) {\n      insertElement(type, this.media, {\n        src: attributes,\n      });\n    } else if (is.array(attributes)) {\n      attributes.forEach((attribute) => {\n        insertElement(type, this.media, attribute);\n      });\n    }\n  },\n\n  // Update source\n  // Sources are not checked for support so be careful\n  change(input) {\n    if (!getDeep(input, 'sources.length')) {\n      this.debug.warn('Invalid source format');\n      return;\n    }\n\n    // Cancel current network requests\n    html5.cancelRequests.call(this);\n\n    // Destroy instance and re-setup\n    this.destroy.call(\n      this,\n      () => {\n        // Reset quality options\n        this.options.quality = [];\n\n        // Remove elements\n        removeElement(this.media);\n        this.media = null;\n\n        // Reset class name\n        if (is.element(this.elements.container)) {\n          this.elements.container.removeAttribute('class');\n        }\n\n        // Set the type and provider\n        const { sources, type } = input;\n        const [{ provider = providers.html5, src }] = sources;\n        const tagName = provider === 'html5' ? type : 'div';\n        const attributes = provider === 'html5' ? {} : { src };\n\n        Object.assign(this, {\n          provider,\n          type,\n          // Check for support\n          supported: support.check(type, provider, this.config.playsinline),\n          // Create new element\n          media: createElement(tagName, attributes),\n        });\n\n        // Inject the new element\n        this.elements.container.appendChild(this.media);\n\n        // Autoplay the new source?\n        if (is.boolean(input.autoplay)) {\n          this.config.autoplay = input.autoplay;\n        }\n\n        // Set attributes for audio and video\n        if (this.isHTML5) {\n          if (this.config.crossorigin) {\n            this.media.setAttribute('crossorigin', '');\n          }\n          if (this.config.autoplay) {\n            this.media.setAttribute('autoplay', '');\n          }\n          if (!is.empty(input.poster)) {\n            this.poster = input.poster;\n          }\n          if (this.config.loop.active) {\n            this.media.setAttribute('loop', '');\n          }\n          if (this.config.muted) {\n            this.media.setAttribute('muted', '');\n          }\n          if (this.config.playsinline) {\n            this.media.setAttribute('playsinline', '');\n          }\n        }\n\n        // Restore class hook\n        ui.addStyleHook.call(this);\n\n        // Set new sources for html5\n        if (this.isHTML5) {\n          source.insertElements.call(this, 'source', sources);\n        }\n\n        // Set video title\n        this.config.title = input.title;\n\n        // Set up from scratch\n        media.setup.call(this);\n\n        // HTML5 stuff\n        if (this.isHTML5) {\n          // Setup captions\n          if (Object.keys(input).includes('tracks')) {\n            source.insertElements.call(this, 'track', input.tracks);\n          }\n        }\n\n        // If HTML5 or embed but not fully supported, setupInterface and call ready now\n        if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n          // Setup interface\n          ui.build.call(this);\n        }\n\n        // Load HTML5 sources\n        if (this.isHTML5) {\n          this.media.load();\n        }\n\n        // Update previewThumbnails config & reload plugin\n        if (!is.empty(input.previewThumbnails)) {\n          Object.assign(this.config.previewThumbnails, input.previewThumbnails);\n\n          // Cleanup previewThumbnails plugin if it was loaded\n          if (this.previewThumbnails && this.previewThumbnails.loaded) {\n            this.previewThumbnails.destroy();\n            this.previewThumbnails = null;\n          }\n\n          // Create new instance if it is still enabled\n          if (this.config.previewThumbnails.enabled) {\n            this.previewThumbnails = new PreviewThumbnails(this);\n          }\n        }\n\n        // Update the fullscreen support\n        this.fullscreen.update();\n      },\n      true,\n    );\n  },\n};\n\nexport default source;\n", "// ==========================================================================\n// Plyr\n// plyr.js v3.6.12\n// https://github.com/sampotts/plyr\n// License: The MIT License (MIT)\n// ==========================================================================\n\nimport captions from './captions';\nimport defaults from './config/defaults';\nimport { pip } from './config/states';\nimport { getProviderByUrl, providers, types } from './config/types';\nimport Console from './console';\nimport controls from './controls';\nimport Fullscreen from './fullscreen';\nimport html5 from './html5';\nimport Listeners from './listeners';\nimport media from './media';\nimport Ads from './plugins/ads';\nimport PreviewThumbnails from './plugins/preview-thumbnails';\nimport source from './source';\nimport Storage from './storage';\nimport support from './support';\nimport ui from './ui';\nimport { closest } from './utils/arrays';\nimport { createElement, hasClass, removeElement, replaceElement, toggleClass, wrap } from './utils/elements';\nimport { off, on, once, triggerEvent, unbindListeners } from './utils/events';\nimport is from './utils/is';\nimport loadSprite from './utils/load-sprite';\nimport { clamp } from './utils/numbers';\nimport { cloneDeep, extend } from './utils/objects';\nimport { silencePromise } from './utils/promise';\nimport { getAspectRatio, reduceAspectRatio, setAspectRatio, validateAspectRatio } from './utils/style';\nimport { parseUrl } from './utils/urls';\n\n// Private properties\n// TODO: Use a WeakMap for private globals\n// const globals = new WeakMap();\n\n// Plyr instance\nclass Plyr {\n  constructor(target, options) {\n    this.timers = {};\n\n    // State\n    this.ready = false;\n    this.loading = false;\n    this.failed = false;\n\n    // Touch device\n    this.touch = support.touch;\n\n    // Set the media element\n    this.media = target;\n\n    // String selector passed\n    if (is.string(this.media)) {\n      this.media = document.querySelectorAll(this.media);\n    }\n\n    // jQuery, NodeList or Array passed, use first element\n    if ((window.jQuery && this.media instanceof jQuery) || is.nodeList(this.media) || is.array(this.media)) {\n      // eslint-disable-next-line\n      this.media = this.media[0];\n    }\n\n    // Set config\n    this.config = extend(\n      {},\n      defaults,\n      Plyr.defaults,\n      options || {},\n      (() => {\n        try {\n          return JSON.parse(this.media.getAttribute('data-plyr-config'));\n        } catch (_) {\n          return {};\n        }\n      })(),\n    );\n\n    // Elements cache\n    this.elements = {\n      container: null,\n      fullscreen: null,\n      captions: null,\n      buttons: {},\n      display: {},\n      progress: {},\n      inputs: {},\n      settings: {\n        popup: null,\n        menu: null,\n        panels: {},\n        buttons: {},\n      },\n    };\n\n    // Captions\n    this.captions = {\n      active: null,\n      currentTrack: -1,\n      meta: new WeakMap(),\n    };\n\n    // Fullscreen\n    this.fullscreen = {\n      active: false,\n    };\n\n    // Options\n    this.options = {\n      speed: [],\n      quality: [],\n    };\n\n    // Debugging\n    // TODO: move to globals\n    this.debug = new Console(this.config.debug);\n\n    // Log config options and support\n    this.debug.log('Config', this.config);\n    this.debug.log('Support', support);\n\n    // We need an element to setup\n    if (is.nullOrUndefined(this.media) || !is.element(this.media)) {\n      this.debug.error('Setup failed: no suitable element passed');\n      return;\n    }\n\n    // Bail if the element is initialized\n    if (this.media.plyr) {\n      this.debug.warn('Target already setup');\n      return;\n    }\n\n    // Bail if not enabled\n    if (!this.config.enabled) {\n      this.debug.error('Setup failed: disabled by config');\n      return;\n    }\n\n    // Bail if disabled or no basic support\n    // You may want to disable certain UAs etc\n    if (!support.check().api) {\n      this.debug.error('Setup failed: no support');\n      return;\n    }\n\n    // Cache original element state for .destroy()\n    const clone = this.media.cloneNode(true);\n    clone.autoplay = false;\n    this.elements.original = clone;\n\n    // Set media type based on tag or data attribute\n    // Supported: video, audio, vimeo, youtube\n    const type = this.media.tagName.toLowerCase();\n    // Embed properties\n    let iframe = null;\n    let url = null;\n\n    // Different setup based on type\n    switch (type) {\n      case 'div':\n        // Find the frame\n        iframe = this.media.querySelector('iframe');\n\n        // <iframe> type\n        if (is.element(iframe)) {\n          // Detect provider\n          url = parseUrl(iframe.getAttribute('src'));\n          this.provider = getProviderByUrl(url.toString());\n\n          // Rework elements\n          this.elements.container = this.media;\n          this.media = iframe;\n\n          // Reset classname\n          this.elements.container.className = '';\n\n          // Get attributes from URL and set config\n          if (url.search.length) {\n            const truthy = ['1', 'true'];\n\n            if (truthy.includes(url.searchParams.get('autoplay'))) {\n              this.config.autoplay = true;\n            }\n            if (truthy.includes(url.searchParams.get('loop'))) {\n              this.config.loop.active = true;\n            }\n\n            // TODO: replace fullscreen.iosNative with this playsinline config option\n            // YouTube requires the playsinline in the URL\n            if (this.isYouTube) {\n              this.config.playsinline = truthy.includes(url.searchParams.get('playsinline'));\n              this.config.youtube.hl = url.searchParams.get('hl'); // TODO: Should this be setting language?\n            } else {\n              this.config.playsinline = true;\n            }\n          }\n        } else {\n          // <div> with attributes\n          this.provider = this.media.getAttribute(this.config.attributes.embed.provider);\n\n          // Remove attribute\n          this.media.removeAttribute(this.config.attributes.embed.provider);\n        }\n\n        // Unsupported or missing provider\n        if (is.empty(this.provider) || !Object.values(providers).includes(this.provider)) {\n          this.debug.error('Setup failed: Invalid provider');\n          return;\n        }\n\n        // Audio will come later for external providers\n        this.type = types.video;\n\n        break;\n\n      case 'video':\n      case 'audio':\n        this.type = type;\n        this.provider = providers.html5;\n\n        // Get config from attributes\n        if (this.media.hasAttribute('crossorigin')) {\n          this.config.crossorigin = true;\n        }\n        if (this.media.hasAttribute('autoplay')) {\n          this.config.autoplay = true;\n        }\n        if (this.media.hasAttribute('playsinline') || this.media.hasAttribute('webkit-playsinline')) {\n          this.config.playsinline = true;\n        }\n        if (this.media.hasAttribute('muted')) {\n          this.config.muted = true;\n        }\n        if (this.media.hasAttribute('loop')) {\n          this.config.loop.active = true;\n        }\n\n        break;\n\n      default:\n        this.debug.error('Setup failed: unsupported type');\n        return;\n    }\n\n    // Check for support again but with type\n    this.supported = support.check(this.type, this.provider, this.config.playsinline);\n\n    // If no support for even API, bail\n    if (!this.supported.api) {\n      this.debug.error('Setup failed: no support');\n      return;\n    }\n\n    this.eventListeners = [];\n\n    // Create listeners\n    this.listeners = new Listeners(this);\n\n    // Setup local storage for user settings\n    this.storage = new Storage(this);\n\n    // Store reference\n    this.media.plyr = this;\n\n    // Wrap media\n    if (!is.element(this.elements.container)) {\n      this.elements.container = createElement('div', { tabindex: 0 });\n      wrap(this.media, this.elements.container);\n    }\n\n    // Migrate custom properties from media to container (so they work \uD83D\uDE09)\n    ui.migrateStyles.call(this);\n\n    // Add style hook\n    ui.addStyleHook.call(this);\n\n    // Setup media\n    media.setup.call(this);\n\n    // Listen for events if debugging\n    if (this.config.debug) {\n      on.call(this, this.elements.container, this.config.events.join(' '), (event) => {\n        this.debug.log(`event: ${event.type}`);\n      });\n    }\n\n    // Setup fullscreen\n    this.fullscreen = new Fullscreen(this);\n\n    // Setup interface\n    // If embed but not fully supported, build interface now to avoid flash of controls\n    if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n      ui.build.call(this);\n    }\n\n    // Container listeners\n    this.listeners.container();\n\n    // Global listeners\n    this.listeners.global();\n\n    // Setup ads if provided\n    if (this.config.ads.enabled) {\n      this.ads = new Ads(this);\n    }\n\n    // Autoplay if required\n    if (this.isHTML5 && this.config.autoplay) {\n      this.once('canplay', () => silencePromise(this.play()));\n    }\n\n    // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek\n    this.lastSeekTime = 0;\n\n    // Setup preview thumbnails if enabled\n    if (this.config.previewThumbnails.enabled) {\n      this.previewThumbnails = new PreviewThumbnails(this);\n    }\n  }\n\n  // ---------------------------------------\n  // API\n  // ---------------------------------------\n\n  /**\n   * Types and provider helpers\n   */\n  get isHTML5() {\n    return this.provider === providers.html5;\n  }\n\n  get isEmbed() {\n    return this.isYouTube || this.isVimeo;\n  }\n\n  get isYouTube() {\n    return this.provider === providers.youtube;\n  }\n\n  get isVimeo() {\n    return this.provider === providers.vimeo;\n  }\n\n  get isVideo() {\n    return this.type === types.video;\n  }\n\n  get isAudio() {\n    return this.type === types.audio;\n  }\n\n  /**\n   * Play the media, or play the advertisement (if they are not blocked)\n   */\n  play = () => {\n    if (!is.function(this.media.play)) {\n      return null;\n    }\n\n    // Intecept play with ads\n    if (this.ads && this.ads.enabled) {\n      this.ads.managerPromise.then(() => this.ads.play()).catch(() => silencePromise(this.media.play()));\n    }\n\n    // Return the promise (for HTML5)\n    return this.media.play();\n  };\n\n  /**\n   * Pause the media\n   */\n  pause = () => {\n    if (!this.playing || !is.function(this.media.pause)) {\n      return null;\n    }\n\n    return this.media.pause();\n  };\n\n  /**\n   * Get playing state\n   */\n  get playing() {\n    return Boolean(this.ready && !this.paused && !this.ended);\n  }\n\n  /**\n   * Get paused state\n   */\n  get paused() {\n    return Boolean(this.media.paused);\n  }\n\n  /**\n   * Get stopped state\n   */\n  get stopped() {\n    return Boolean(this.paused && this.currentTime === 0);\n  }\n\n  /**\n   * Get ended state\n   */\n  get ended() {\n    return Boolean(this.media.ended);\n  }\n\n  /**\n   * Toggle playback based on current status\n   * @param {Boolean} input\n   */\n  togglePlay = (input) => {\n    // Toggle based on current state if nothing passed\n    const toggle = is.boolean(input) ? input : !this.playing;\n\n    if (toggle) {\n      return this.play();\n    }\n\n    return this.pause();\n  };\n\n  /**\n   * Stop playback\n   */\n  stop = () => {\n    if (this.isHTML5) {\n      this.pause();\n      this.restart();\n    } else if (is.function(this.media.stop)) {\n      this.media.stop();\n    }\n  };\n\n  /**\n   * Restart playback\n   */\n  restart = () => {\n    this.currentTime = 0;\n  };\n\n  /**\n   * Rewind\n   * @param {Number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime\n   */\n  rewind = (seekTime) => {\n    this.currentTime -= is.number(seekTime) ? seekTime : this.config.seekTime;\n  };\n\n  /**\n   * Fast forward\n   * @param {Number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime\n   */\n  forward = (seekTime) => {\n    this.currentTime += is.number(seekTime) ? seekTime : this.config.seekTime;\n  };\n\n  /**\n   * Seek to a time\n   * @param {Number} input - where to seek to in seconds. Defaults to 0 (the start)\n   */\n  set currentTime(input) {\n    // Bail if media duration isn't available yet\n    if (!this.duration) {\n      return;\n    }\n\n    // Validate input\n    const inputIsValid = is.number(input) && input > 0;\n\n    // Set\n    this.media.currentTime = inputIsValid ? Math.min(input, this.duration) : 0;\n\n    // Logging\n    this.debug.log(`Seeking to ${this.currentTime} seconds`);\n  }\n\n  /**\n   * Get current time\n   */\n  get currentTime() {\n    return Number(this.media.currentTime);\n  }\n\n  /**\n   * Get buffered\n   */\n  get buffered() {\n    const { buffered } = this.media;\n\n    // YouTube / Vimeo return a float between 0-1\n    if (is.number(buffered)) {\n      return buffered;\n    }\n\n    // HTML5\n    // TODO: Handle buffered chunks of the media\n    // (i.e. seek to another section buffers only that section)\n    if (buffered && buffered.length && this.duration > 0) {\n      return buffered.end(0) / this.duration;\n    }\n\n    return 0;\n  }\n\n  /**\n   * Get seeking status\n   */\n  get seeking() {\n    return Boolean(this.media.seeking);\n  }\n\n  /**\n   * Get the duration of the current media\n   */\n  get duration() {\n    // Faux duration set via config\n    const fauxDuration = parseFloat(this.config.duration);\n    // Media duration can be NaN or Infinity before the media has loaded\n    const realDuration = (this.media || {}).duration;\n    const duration = !is.number(realDuration) || realDuration === Infinity ? 0 : realDuration;\n\n    // If config duration is funky, use regular duration\n    return fauxDuration || duration;\n  }\n\n  /**\n   * Set the player volume\n   * @param {Number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage\n   */\n  set volume(value) {\n    let volume = value;\n    const max = 1;\n    const min = 0;\n\n    if (is.string(volume)) {\n      volume = Number(volume);\n    }\n\n    // Load volume from storage if no value specified\n    if (!is.number(volume)) {\n      volume = this.storage.get('volume');\n    }\n\n    // Use config if all else fails\n    if (!is.number(volume)) {\n      ({ volume } = this.config);\n    }\n\n    // Maximum is volumeMax\n    if (volume > max) {\n      volume = max;\n    }\n    // Minimum is volumeMin\n    if (volume < min) {\n      volume = min;\n    }\n\n    // Update config\n    this.config.volume = volume;\n\n    // Set the player volume\n    this.media.volume = volume;\n\n    // If muted, and we're increasing volume manually, reset muted state\n    if (!is.empty(value) && this.muted && volume > 0) {\n      this.muted = false;\n    }\n  }\n\n  /**\n   * Get the current player volume\n   */\n  get volume() {\n    return Number(this.media.volume);\n  }\n\n  /**\n   * Increase volume\n   * @param {Boolean} step - How much to decrease by (between 0 and 1)\n   */\n  increaseVolume = (step) => {\n    const volume = this.media.muted ? 0 : this.volume;\n    this.volume = volume + (is.number(step) ? step : 0);\n  };\n\n  /**\n   * Decrease volume\n   * @param {Boolean} step - How much to decrease by (between 0 and 1)\n   */\n  decreaseVolume = (step) => {\n    this.increaseVolume(-step);\n  };\n\n  /**\n   * Set muted state\n   * @param {Boolean} mute\n   */\n  set muted(mute) {\n    let toggle = mute;\n\n    // Load muted state from storage\n    if (!is.boolean(toggle)) {\n      toggle = this.storage.get('muted');\n    }\n\n    // Use config if all else fails\n    if (!is.boolean(toggle)) {\n      toggle = this.config.muted;\n    }\n\n    // Update config\n    this.config.muted = toggle;\n\n    // Set mute on the player\n    this.media.muted = toggle;\n  }\n\n  /**\n   * Get current muted state\n   */\n  get muted() {\n    return Boolean(this.media.muted);\n  }\n\n  /**\n   * Check if the media has audio\n   */\n  get hasAudio() {\n    // Assume yes for all non HTML5 (as we can't tell...)\n    if (!this.isHTML5) {\n      return true;\n    }\n\n    if (this.isAudio) {\n      return true;\n    }\n\n    // Get audio tracks\n    return (\n      Boolean(this.media.mozHasAudio) ||\n      Boolean(this.media.webkitAudioDecodedByteCount) ||\n      Boolean(this.media.audioTracks && this.media.audioTracks.length)\n    );\n  }\n\n  /**\n   * Set playback speed\n   * @param {Number} speed - the speed of playback (0.5-2.0)\n   */\n  set speed(input) {\n    let speed = null;\n\n    if (is.number(input)) {\n      speed = input;\n    }\n\n    if (!is.number(speed)) {\n      speed = this.storage.get('speed');\n    }\n\n    if (!is.number(speed)) {\n      speed = this.config.speed.selected;\n    }\n\n    // Clamp to min/max\n    const { minimumSpeed: min, maximumSpeed: max } = this;\n    speed = clamp(speed, min, max);\n\n    // Update config\n    this.config.speed.selected = speed;\n\n    // Set media speed\n    setTimeout(() => {\n      if (this.media) {\n        this.media.playbackRate = speed;\n      }\n    }, 0);\n  }\n\n  /**\n   * Get current playback speed\n   */\n  get speed() {\n    return Number(this.media.playbackRate);\n  }\n\n  /**\n   * Get the minimum allowed speed\n   */\n  get minimumSpeed() {\n    if (this.isYouTube) {\n      // https://developers.google.com/youtube/iframe_api_reference#setPlaybackRate\n      return Math.min(...this.options.speed);\n    }\n\n    if (this.isVimeo) {\n      // https://github.com/vimeo/player.js/#setplaybackrateplaybackrate-number-promisenumber-rangeerrorerror\n      return 0.5;\n    }\n\n    // https://stackoverflow.com/a/32320020/1191319\n    return 0.0625;\n  }\n\n  /**\n   * Get the maximum allowed speed\n   */\n  get maximumSpeed() {\n    if (this.isYouTube) {\n      // https://developers.google.com/youtube/iframe_api_reference#setPlaybackRate\n      return Math.max(...this.options.speed);\n    }\n\n    if (this.isVimeo) {\n      // https://github.com/vimeo/player.js/#setplaybackrateplaybackrate-number-promisenumber-rangeerrorerror\n      return 2;\n    }\n\n    // https://stackoverflow.com/a/32320020/1191319\n    return 16;\n  }\n\n  /**\n   * Set playback quality\n   * Currently HTML5 & YouTube only\n   * @param {Number} input - Quality level\n   */\n  set quality(input) {\n    const config = this.config.quality;\n    const options = this.options.quality;\n\n    if (!options.length) {\n      return;\n    }\n\n    let quality = [\n      !is.empty(input) && Number(input),\n      this.storage.get('quality'),\n      config.selected,\n      config.default,\n    ].find(is.number);\n\n    let updateStorage = true;\n\n    if (!options.includes(quality)) {\n      const value = closest(options, quality);\n      this.debug.warn(`Unsupported quality option: ${quality}, using ${value} instead`);\n      quality = value;\n\n      // Don't update storage if quality is not supported\n      updateStorage = false;\n    }\n\n    // Update config\n    config.selected = quality;\n\n    // Set quality\n    this.media.quality = quality;\n\n    // Save to storage\n    if (updateStorage) {\n      this.storage.set({ quality });\n    }\n  }\n\n  /**\n   * Get current quality level\n   */\n  get quality() {\n    return this.media.quality;\n  }\n\n  /**\n   * Toggle loop\n   * TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config\n   * @param {Boolean} input - Whether to loop or not\n   */\n  set loop(input) {\n    const toggle = is.boolean(input) ? input : this.config.loop.active;\n    this.config.loop.active = toggle;\n    this.media.loop = toggle;\n\n    // Set default to be a true toggle\n    /* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle';\n\n        switch (type) {\n            case 'start':\n                if (this.config.loop.end && this.config.loop.end <= this.currentTime) {\n                    this.config.loop.end = null;\n                }\n                this.config.loop.start = this.currentTime;\n                // this.config.loop.indicator.start = this.elements.display.played.value;\n                break;\n\n            case 'end':\n                if (this.config.loop.start >= this.currentTime) {\n                    return this;\n                }\n                this.config.loop.end = this.currentTime;\n                // this.config.loop.indicator.end = this.elements.display.played.value;\n                break;\n\n            case 'all':\n                this.config.loop.start = 0;\n                this.config.loop.end = this.duration - 2;\n                this.config.loop.indicator.start = 0;\n                this.config.loop.indicator.end = 100;\n                break;\n\n            case 'toggle':\n                if (this.config.loop.active) {\n                    this.config.loop.start = 0;\n                    this.config.loop.end = null;\n                } else {\n                    this.config.loop.start = 0;\n                    this.config.loop.end = this.duration - 2;\n                }\n                break;\n\n            default:\n                this.config.loop.start = 0;\n                this.config.loop.end = null;\n                break;\n        } */\n  }\n\n  /**\n   * Get current loop state\n   */\n  get loop() {\n    return Boolean(this.media.loop);\n  }\n\n  /**\n   * Set new media source\n   * @param {Object} input - The new source object (see docs)\n   */\n  set source(input) {\n    source.change.call(this, input);\n  }\n\n  /**\n   * Get current source\n   */\n  get source() {\n    return this.media.currentSrc;\n  }\n\n  /**\n   * Get a download URL (either source or custom)\n   */\n  get download() {\n    const { download } = this.config.urls;\n\n    return is.url(download) ? download : this.source;\n  }\n\n  /**\n   * Set the download URL\n   */\n  set download(input) {\n    if (!is.url(input)) {\n      return;\n    }\n\n    this.config.urls.download = input;\n\n    controls.setDownloadUrl.call(this);\n  }\n\n  /**\n   * Set the poster image for a video\n   * @param {String} input - the URL for the new poster image\n   */\n  set poster(input) {\n    if (!this.isVideo) {\n      this.debug.warn('Poster can only be set for video');\n      return;\n    }\n\n    ui.setPoster.call(this, input, false).catch(() => {});\n  }\n\n  /**\n   * Get the current poster image\n   */\n  get poster() {\n    if (!this.isVideo) {\n      return null;\n    }\n\n    return this.media.getAttribute('poster') || this.media.getAttribute('data-poster');\n  }\n\n  /**\n   * Get the current aspect ratio in use\n   */\n  get ratio() {\n    if (!this.isVideo) {\n      return null;\n    }\n\n    const ratio = reduceAspectRatio(getAspectRatio.call(this));\n\n    return is.array(ratio) ? ratio.join(':') : ratio;\n  }\n\n  /**\n   * Set video aspect ratio\n   */\n  set ratio(input) {\n    if (!this.isVideo) {\n      this.debug.warn('Aspect ratio can only be set for video');\n      return;\n    }\n\n    if (!is.string(input) || !validateAspectRatio(input)) {\n      this.debug.error(`Invalid aspect ratio specified (${input})`);\n      return;\n    }\n\n    this.config.ratio = reduceAspectRatio(input);\n\n    setAspectRatio.call(this);\n  }\n\n  /**\n   * Set the autoplay state\n   * @param {Boolean} input - Whether to autoplay or not\n   */\n  set autoplay(input) {\n    const toggle = is.boolean(input) ? input : this.config.autoplay;\n    this.config.autoplay = toggle;\n  }\n\n  /**\n   * Get the current autoplay state\n   */\n  get autoplay() {\n    return Boolean(this.config.autoplay);\n  }\n\n  /**\n   * Toggle captions\n   * @param {Boolean} input - Whether to enable captions\n   */\n  toggleCaptions(input) {\n    captions.toggle.call(this, input, false);\n  }\n\n  /**\n   * Set the caption track by index\n   * @param {Number} - Caption index\n   */\n  set currentTrack(input) {\n    captions.set.call(this, input, false);\n    captions.setup();\n  }\n\n  /**\n   * Get the current caption track index (-1 if disabled)\n   */\n  get currentTrack() {\n    const { toggled, currentTrack } = this.captions;\n    return toggled ? currentTrack : -1;\n  }\n\n  /**\n   * Set the wanted language for captions\n   * Since tracks can be added later it won't update the actual caption track until there is a matching track\n   * @param {String} - Two character ISO language code (e.g. EN, FR, PT, etc)\n   */\n  set language(input) {\n    captions.setLanguage.call(this, input, false);\n  }\n\n  /**\n   * Get the current track's language\n   */\n  get language() {\n    return (captions.getCurrentTrack.call(this) || {}).language;\n  }\n\n  /**\n   * Toggle picture-in-picture playback on WebKit/MacOS\n   * TODO: update player with state, support, enabled\n   * TODO: detect outside changes\n   */\n  set pip(input) {\n    // Bail if no support\n    if (!support.pip) {\n      return;\n    }\n\n    // Toggle based on current state if not passed\n    const toggle = is.boolean(input) ? input : !this.pip;\n\n    // Toggle based on current state\n    // Safari\n    if (is.function(this.media.webkitSetPresentationMode)) {\n      this.media.webkitSetPresentationMode(toggle ? pip.active : pip.inactive);\n    }\n\n    // Chrome\n    if (is.function(this.media.requestPictureInPicture)) {\n      if (!this.pip && toggle) {\n        this.media.requestPictureInPicture();\n      } else if (this.pip && !toggle) {\n        document.exitPictureInPicture();\n      }\n    }\n  }\n\n  /**\n   * Get the current picture-in-picture state\n   */\n  get pip() {\n    if (!support.pip) {\n      return null;\n    }\n\n    // Safari\n    if (!is.empty(this.media.webkitPresentationMode)) {\n      return this.media.webkitPresentationMode === pip.active;\n    }\n\n    // Chrome\n    return this.media === document.pictureInPictureElement;\n  }\n\n  /**\n   * Sets the preview thubmnails for the current source\n   */\n  setPreviewThumbnails(thumbnailSource) {\n    if (this.previewThumbnails && this.previewThumbnails.loaded) {\n      this.previewThumbnails.destroy();\n      this.previewThumbnails = null;\n    }\n\n    Object.assign(this.config.previewThumbnails, thumbnailSource);\n\n    // Create new instance if it is still enabled\n    if (this.config.previewThumbnails.enabled) {\n      this.previewThumbnails = new PreviewThumbnails(this);\n    }\n  }\n\n  /**\n   * Trigger the airplay dialog\n   * TODO: update player with state, support, enabled\n   */\n  airplay = () => {\n    // Show dialog if supported\n    if (support.airplay) {\n      this.media.webkitShowPlaybackTargetPicker();\n    }\n  };\n\n  /**\n   * Toggle the player controls\n   * @param {Boolean} [toggle] - Whether to show the controls\n   */\n  toggleControls = (toggle) => {\n    // Don't toggle if missing UI support or if it's audio\n    if (this.supported.ui && !this.isAudio) {\n      // Get state before change\n      const isHidden = hasClass(this.elements.container, this.config.classNames.hideControls);\n      // Negate the argument if not undefined since adding the class to hides the controls\n      const force = typeof toggle === 'undefined' ? undefined : !toggle;\n      // Apply and get updated state\n      const hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force);\n\n      // Close menu\n      if (\n        hiding &&\n        is.array(this.config.controls) &&\n        this.config.controls.includes('settings') &&\n        !is.empty(this.config.settings)\n      ) {\n        controls.toggleMenu.call(this, false);\n      }\n\n      // Trigger event on change\n      if (hiding !== isHidden) {\n        const eventName = hiding ? 'controlshidden' : 'controlsshown';\n        triggerEvent.call(this, this.media, eventName);\n      }\n\n      return !hiding;\n    }\n\n    return false;\n  };\n\n  /**\n   * Add event listeners\n   * @param {String} event - Event type\n   * @param {Function} callback - Callback for when event occurs\n   */\n  on = (event, callback) => {\n    on.call(this, this.elements.container, event, callback);\n  };\n\n  /**\n   * Add event listeners once\n   * @param {String} event - Event type\n   * @param {Function} callback - Callback for when event occurs\n   */\n  once = (event, callback) => {\n    once.call(this, this.elements.container, event, callback);\n  };\n\n  /**\n   * Remove event listeners\n   * @param {String} event - Event type\n   * @param {Function} callback - Callback for when event occurs\n   */\n  off = (event, callback) => {\n    off(this.elements.container, event, callback);\n  };\n\n  /**\n   * Destroy an instance\n   * Event listeners are removed when elements are removed\n   * http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory\n   * @param {Function} callback - Callback for when destroy is complete\n   * @param {Boolean} soft - Whether it's a soft destroy (for source changes etc)\n   */\n  destroy = (callback, soft = false) => {\n    if (!this.ready) {\n      return;\n    }\n\n    const done = () => {\n      // Reset overflow (incase destroyed while in fullscreen)\n      document.body.style.overflow = '';\n\n      // GC for embed\n      this.embed = null;\n\n      // If it's a soft destroy, make minimal changes\n      if (soft) {\n        if (Object.keys(this.elements).length) {\n          // Remove elements\n          removeElement(this.elements.buttons.play);\n          removeElement(this.elements.captions);\n          removeElement(this.elements.controls);\n          removeElement(this.elements.wrapper);\n\n          // Clear for GC\n          this.elements.buttons.play = null;\n          this.elements.captions = null;\n          this.elements.controls = null;\n          this.elements.wrapper = null;\n        }\n\n        // Callback\n        if (is.function(callback)) {\n          callback();\n        }\n      } else {\n        // Unbind listeners\n        unbindListeners.call(this);\n\n        // Cancel current network requests\n        html5.cancelRequests.call(this);\n\n        // Replace the container with the original element provided\n        replaceElement(this.elements.original, this.elements.container);\n\n        // Event\n        triggerEvent.call(this, this.elements.original, 'destroyed', true);\n\n        // Callback\n        if (is.function(callback)) {\n          callback.call(this.elements.original);\n        }\n\n        // Reset state\n        this.ready = false;\n\n        // Clear for garbage collection\n        setTimeout(() => {\n          this.elements = null;\n          this.media = null;\n        }, 200);\n      }\n    };\n\n    // Stop playback\n    this.stop();\n\n    // Clear timeouts\n    clearTimeout(this.timers.loading);\n    clearTimeout(this.timers.controls);\n    clearTimeout(this.timers.resized);\n\n    // Provider specific stuff\n    if (this.isHTML5) {\n      // Restore native video controls\n      ui.toggleNativeControls.call(this, true);\n\n      // Clean up\n      done();\n    } else if (this.isYouTube) {\n      // Clear timers\n      clearInterval(this.timers.buffering);\n      clearInterval(this.timers.playing);\n\n      // Destroy YouTube API\n      if (this.embed !== null && is.function(this.embed.destroy)) {\n        this.embed.destroy();\n      }\n\n      // Clean up\n      done();\n    } else if (this.isVimeo) {\n      // Destroy Vimeo API\n      // then clean up (wait, to prevent postmessage errors)\n      if (this.embed !== null) {\n        this.embed.unload().then(done);\n      }\n\n      // Vimeo does not always return\n      setTimeout(done, 200);\n    }\n  };\n\n  /**\n   * Check for support for a mime type (HTML5 only)\n   * @param {String} type - Mime type\n   */\n  supports = (type) => support.mime.call(this, type);\n\n  /**\n   * Check for support\n   * @param {String} type - Player type (audio/video)\n   * @param {String} provider - Provider (html5/youtube/vimeo)\n   * @param {Boolean} inline - Where player has `playsinline` sttribute\n   */\n  static supported(type, provider, inline) {\n    return support.check(type, provider, inline);\n  }\n\n  /**\n   * Load an SVG sprite into the page\n   * @param {String} url - URL for the SVG sprite\n   * @param {String} [id] - Unique ID\n   */\n  static loadSprite(url, id) {\n    return loadSprite(url, id);\n  }\n\n  /**\n   * Setup multiple instances\n   * @param {*} selector\n   * @param {Object} options\n   */\n  static setup(selector, options = {}) {\n    let targets = null;\n\n    if (is.string(selector)) {\n      targets = Array.from(document.querySelectorAll(selector));\n    } else if (is.nodeList(selector)) {\n      targets = Array.from(selector);\n    } else if (is.array(selector)) {\n      targets = selector.filter(is.element);\n    }\n\n    if (is.empty(targets)) {\n      return null;\n    }\n\n    return targets.map((t) => new Plyr(t, options));\n  }\n}\n\nPlyr.defaults = cloneDeep(defaults);\n\nexport default Plyr;\n", "/**\n * Returns a number whose value is limited to the given range.\n *\n * Example: limit the output of this computation to between 0 and 255\n * (x * 255).clamp(0, 255)\n *\n * @param {Number} input\n * @param {Number} min The lower boundary of the output range\n * @param {Number} max The upper boundary of the output range\n * @returns A number in the range [min, max]\n * @type Number\n */\nexport function clamp(input = 0, min = 0, max = 255) {\n  return Math.min(Math.max(input, min), max);\n}\n\nexport default { clamp };\n", "// packages/persist/src/index.js\nfunction src_default(Alpine) {\n  let persist = () => {\n    let alias;\n    let storage = localStorage;\n    return Alpine.interceptor((initialValue, getter, setter, path, key) => {\n      let lookup = alias || `_x_${path}`;\n      let initial = storageHas(lookup, storage) ? storageGet(lookup, storage) : initialValue;\n      setter(initial);\n      Alpine.effect(() => {\n        let value = getter();\n        storageSet(lookup, value, storage);\n        setter(value);\n      });\n      return initial;\n    }, (func) => {\n      func.as = (key) => {\n        alias = key;\n        return func;\n      }, func.using = (target) => {\n        storage = target;\n        return func;\n      };\n    });\n  };\n  Object.defineProperty(Alpine, \"$persist\", {get: () => persist()});\n  Alpine.magic(\"persist\", persist);\n}\nfunction storageHas(key, storage) {\n  return storage.getItem(key) !== null;\n}\nfunction storageGet(key, storage) {\n  return JSON.parse(storage.getItem(key, storage));\n}\nfunction storageSet(key, value, storage) {\n  storage.setItem(key, JSON.stringify(value));\n}\n\n// packages/persist/builds/module.js\nvar module_default = src_default;\nexport {\n  module_default as default\n};\n", "function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, \"prototype\", { writable: false }); return Constructor; }\n\n/*!\n * Splide.js\n * Version  : 4.0.1\n * License  : MIT\n * Copyright: 2022 Naotoshi Fujita\n */\nvar MEDIA_PREFERS_REDUCED_MOTION = \"(prefers-reduced-motion: reduce)\";\nvar CREATED = 1;\nvar MOUNTED = 2;\nvar IDLE = 3;\nvar MOVING = 4;\nvar SCROLLING = 5;\nvar DRAGGING = 6;\nvar DESTROYED = 7;\nvar STATES = {\n  CREATED: CREATED,\n  MOUNTED: MOUNTED,\n  IDLE: IDLE,\n  MOVING: MOVING,\n  SCROLLING: SCROLLING,\n  DRAGGING: DRAGGING,\n  DESTROYED: DESTROYED\n};\n\nfunction empty(array) {\n  array.length = 0;\n}\n\nfunction slice(arrayLike, start, end) {\n  return Array.prototype.slice.call(arrayLike, start, end);\n}\n\nfunction apply(func) {\n  return func.bind.apply(func, [null].concat(slice(arguments, 1)));\n}\n\nvar nextTick = setTimeout;\n\nvar noop = function noop() {};\n\nfunction raf(func) {\n  return requestAnimationFrame(func);\n}\n\nfunction typeOf(type, subject) {\n  return typeof subject === type;\n}\n\nfunction isObject(subject) {\n  return !isNull(subject) && typeOf(\"object\", subject);\n}\n\nvar isArray = Array.isArray;\nvar isFunction = apply(typeOf, \"function\");\nvar isString = apply(typeOf, \"string\");\nvar isUndefined = apply(typeOf, \"undefined\");\n\nfunction isNull(subject) {\n  return subject === null;\n}\n\nfunction isHTMLElement(subject) {\n  return subject instanceof HTMLElement;\n}\n\nfunction toArray(value) {\n  return isArray(value) ? value : [value];\n}\n\nfunction forEach(values, iteratee) {\n  toArray(values).forEach(iteratee);\n}\n\nfunction includes(array, value) {\n  return array.indexOf(value) > -1;\n}\n\nfunction push(array, items) {\n  array.push.apply(array, toArray(items));\n  return array;\n}\n\nfunction toggleClass(elm, classes, add) {\n  if (elm) {\n    forEach(classes, function (name) {\n      if (name) {\n        elm.classList[add ? \"add\" : \"remove\"](name);\n      }\n    });\n  }\n}\n\nfunction addClass(elm, classes) {\n  toggleClass(elm, isString(classes) ? classes.split(\" \") : classes, true);\n}\n\nfunction append(parent, children) {\n  forEach(children, parent.appendChild.bind(parent));\n}\n\nfunction before(nodes, ref) {\n  forEach(nodes, function (node) {\n    var parent = (ref || node).parentNode;\n\n    if (parent) {\n      parent.insertBefore(node, ref);\n    }\n  });\n}\n\nfunction matches(elm, selector) {\n  return isHTMLElement(elm) && (elm[\"msMatchesSelector\"] || elm.matches).call(elm, selector);\n}\n\nfunction children(parent, selector) {\n  var children2 = parent ? slice(parent.children) : [];\n  return selector ? children2.filter(function (child) {\n    return matches(child, selector);\n  }) : children2;\n}\n\nfunction child(parent, selector) {\n  return selector ? children(parent, selector)[0] : parent.firstElementChild;\n}\n\nvar ownKeys = Object.keys;\n\nfunction forOwn(object, iteratee, right) {\n  if (object) {\n    var keys = ownKeys(object);\n    keys = right ? keys.reverse() : keys;\n\n    for (var i = 0; i < keys.length; i++) {\n      var key = keys[i];\n\n      if (key !== \"__proto__\") {\n        if (iteratee(object[key], key) === false) {\n          break;\n        }\n      }\n    }\n  }\n\n  return object;\n}\n\nfunction assign(object) {\n  slice(arguments, 1).forEach(function (source) {\n    forOwn(source, function (value, key) {\n      object[key] = source[key];\n    });\n  });\n  return object;\n}\n\nfunction merge(object) {\n  slice(arguments, 1).forEach(function (source) {\n    forOwn(source, function (value, key) {\n      if (isArray(value)) {\n        object[key] = value.slice();\n      } else if (isObject(value)) {\n        object[key] = merge({}, isObject(object[key]) ? object[key] : {}, value);\n      } else {\n        object[key] = value;\n      }\n    });\n  });\n  return object;\n}\n\nfunction omit(object, keys) {\n  toArray(keys || ownKeys(object)).forEach(function (key) {\n    delete object[key];\n  });\n}\n\nfunction removeAttribute(elms, attrs) {\n  forEach(elms, function (elm) {\n    forEach(attrs, function (attr) {\n      elm && elm.removeAttribute(attr);\n    });\n  });\n}\n\nfunction setAttribute(elms, attrs, value) {\n  if (isObject(attrs)) {\n    forOwn(attrs, function (value2, name) {\n      setAttribute(elms, name, value2);\n    });\n  } else {\n    forEach(elms, function (elm) {\n      isNull(value) || value === \"\" ? removeAttribute(elm, attrs) : elm.setAttribute(attrs, String(value));\n    });\n  }\n}\n\nfunction create(tag, attrs, parent) {\n  var elm = document.createElement(tag);\n\n  if (attrs) {\n    isString(attrs) ? addClass(elm, attrs) : setAttribute(elm, attrs);\n  }\n\n  parent && append(parent, elm);\n  return elm;\n}\n\nfunction style(elm, prop, value) {\n  if (isUndefined(value)) {\n    return getComputedStyle(elm)[prop];\n  }\n\n  if (!isNull(value)) {\n    elm.style[prop] = \"\" + value;\n  }\n}\n\nfunction display(elm, display2) {\n  style(elm, \"display\", display2);\n}\n\nfunction focus(elm) {\n  elm[\"setActive\"] && elm[\"setActive\"]() || elm.focus({\n    preventScroll: true\n  });\n}\n\nfunction getAttribute(elm, attr) {\n  return elm.getAttribute(attr);\n}\n\nfunction hasClass(elm, className) {\n  return elm && elm.classList.contains(className);\n}\n\nfunction rect(target) {\n  return target.getBoundingClientRect();\n}\n\nfunction remove(nodes) {\n  forEach(nodes, function (node) {\n    if (node && node.parentNode) {\n      node.parentNode.removeChild(node);\n    }\n  });\n}\n\nfunction parseHtml(html) {\n  return child(new DOMParser().parseFromString(html, \"text/html\").body);\n}\n\nfunction prevent(e, stopPropagation) {\n  e.preventDefault();\n\n  if (stopPropagation) {\n    e.stopPropagation();\n    e.stopImmediatePropagation();\n  }\n}\n\nfunction query(parent, selector) {\n  return parent && parent.querySelector(selector);\n}\n\nfunction queryAll(parent, selector) {\n  return selector ? slice(parent.querySelectorAll(selector)) : [];\n}\n\nfunction removeClass(elm, classes) {\n  toggleClass(elm, classes, false);\n}\n\nfunction timeOf(e) {\n  return e.timeStamp;\n}\n\nfunction unit(value) {\n  return isString(value) ? value : value ? value + \"px\" : \"\";\n}\n\nvar PROJECT_CODE = \"splide\";\nvar DATA_ATTRIBUTE = \"data-\" + PROJECT_CODE;\n\nfunction assert(condition, message) {\n  if (!condition) {\n    throw new Error(\"[\" + PROJECT_CODE + \"] \" + (message || \"\"));\n  }\n}\n\nvar min = Math.min,\n    max = Math.max,\n    floor = Math.floor,\n    ceil = Math.ceil,\n    abs = Math.abs;\n\nfunction approximatelyEqual(x, y, epsilon) {\n  return abs(x - y) < epsilon;\n}\n\nfunction between(number, minOrMax, maxOrMin, exclusive) {\n  var minimum = min(minOrMax, maxOrMin);\n  var maximum = max(minOrMax, maxOrMin);\n  return exclusive ? minimum < number && number < maximum : minimum <= number && number <= maximum;\n}\n\nfunction clamp(number, x, y) {\n  var minimum = min(x, y);\n  var maximum = max(x, y);\n  return min(max(minimum, number), maximum);\n}\n\nfunction sign(x) {\n  return +(x > 0) - +(x < 0);\n}\n\nfunction camelToKebab(string) {\n  return string.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase();\n}\n\nfunction format(string, replacements) {\n  forEach(replacements, function (replacement) {\n    string = string.replace(\"%s\", \"\" + replacement);\n  });\n  return string;\n}\n\nfunction pad(number) {\n  return number < 10 ? \"0\" + number : \"\" + number;\n}\n\nvar ids = {};\n\nfunction uniqueId(prefix) {\n  return \"\" + prefix + pad(ids[prefix] = (ids[prefix] || 0) + 1);\n}\n\nfunction EventBinder() {\n  var listeners = [];\n\n  function bind(targets, events, callback, options) {\n    forEachEvent(targets, events, function (target, event, namespace) {\n      var isEventTarget = (\"addEventListener\" in target);\n      var remover = isEventTarget ? target.removeEventListener.bind(target, event, callback, options) : target[\"removeListener\"].bind(target, callback);\n      isEventTarget ? target.addEventListener(event, callback, options) : target[\"addListener\"](callback);\n      listeners.push([target, event, namespace, callback, remover]);\n    });\n  }\n\n  function unbind(targets, events, callback) {\n    forEachEvent(targets, events, function (target, event, namespace) {\n      listeners = listeners.filter(function (listener) {\n        if (listener[0] === target && listener[1] === event && listener[2] === namespace && (!callback || listener[3] === callback)) {\n          listener[4]();\n          return false;\n        }\n\n        return true;\n      });\n    });\n  }\n\n  function dispatch(target, type, detail) {\n    var e;\n    var bubbles = true;\n\n    if (typeof CustomEvent === \"function\") {\n      e = new CustomEvent(type, {\n        bubbles: bubbles,\n        detail: detail\n      });\n    } else {\n      e = document.createEvent(\"CustomEvent\");\n      e.initCustomEvent(type, bubbles, false, detail);\n    }\n\n    target.dispatchEvent(e);\n    return e;\n  }\n\n  function forEachEvent(targets, events, iteratee) {\n    forEach(targets, function (target) {\n      target && forEach(events, function (events2) {\n        events2.split(\" \").forEach(function (eventNS) {\n          var fragment = eventNS.split(\".\");\n          iteratee(target, fragment[0], fragment[1]);\n        });\n      });\n    });\n  }\n\n  function destroy() {\n    listeners.forEach(function (data) {\n      data[4]();\n    });\n    empty(listeners);\n  }\n\n  return {\n    bind: bind,\n    unbind: unbind,\n    dispatch: dispatch,\n    destroy: destroy\n  };\n}\n\nvar EVENT_MOUNTED = \"mounted\";\nvar EVENT_READY = \"ready\";\nvar EVENT_MOVE = \"move\";\nvar EVENT_MOVED = \"moved\";\nvar EVENT_SHIFTED = \"shifted\";\nvar EVENT_CLICK = \"click\";\nvar EVENT_ACTIVE = \"active\";\nvar EVENT_INACTIVE = \"inactive\";\nvar EVENT_VISIBLE = \"visible\";\nvar EVENT_HIDDEN = \"hidden\";\nvar EVENT_SLIDE_KEYDOWN = \"slide:keydown\";\nvar EVENT_REFRESH = \"refresh\";\nvar EVENT_UPDATED = \"updated\";\nvar EVENT_RESIZE = \"resize\";\nvar EVENT_RESIZED = \"resized\";\nvar EVENT_DRAG = \"drag\";\nvar EVENT_DRAGGING = \"dragging\";\nvar EVENT_DRAGGED = \"dragged\";\nvar EVENT_SCROLL = \"scroll\";\nvar EVENT_SCROLLED = \"scrolled\";\nvar EVENT_DESTROY = \"destroy\";\nvar EVENT_ARROWS_MOUNTED = \"arrows:mounted\";\nvar EVENT_ARROWS_UPDATED = \"arrows:updated\";\nvar EVENT_PAGINATION_MOUNTED = \"pagination:mounted\";\nvar EVENT_PAGINATION_UPDATED = \"pagination:updated\";\nvar EVENT_NAVIGATION_MOUNTED = \"navigation:mounted\";\nvar EVENT_AUTOPLAY_PLAY = \"autoplay:play\";\nvar EVENT_AUTOPLAY_PLAYING = \"autoplay:playing\";\nvar EVENT_AUTOPLAY_PAUSE = \"autoplay:pause\";\nvar EVENT_LAZYLOAD_LOADED = \"lazyload:loaded\";\n\nfunction EventInterface(Splide2) {\n  var bus = Splide2 ? Splide2.event.bus : document.createDocumentFragment();\n  var binder = EventBinder();\n\n  function on(events, callback) {\n    binder.bind(bus, toArray(events).join(\" \"), function (e) {\n      callback.apply(callback, isArray(e.detail) ? e.detail : []);\n    });\n  }\n\n  function emit(event) {\n    binder.dispatch(bus, event, slice(arguments, 1));\n  }\n\n  if (Splide2) {\n    Splide2.event.on(EVENT_DESTROY, binder.destroy);\n  }\n\n  return assign(binder, {\n    bus: bus,\n    on: on,\n    off: apply(binder.unbind, bus),\n    emit: emit\n  });\n}\n\nfunction RequestInterval(interval, onInterval, onUpdate, limit) {\n  var now = Date.now;\n  var startTime;\n  var rate = 0;\n  var id;\n  var paused = true;\n  var count = 0;\n\n  function update() {\n    if (!paused) {\n      rate = interval ? min((now() - startTime) / interval, 1) : 1;\n      onUpdate && onUpdate(rate);\n\n      if (rate >= 1) {\n        onInterval();\n        startTime = now();\n\n        if (limit && ++count >= limit) {\n          return pause();\n        }\n      }\n\n      raf(update);\n    }\n  }\n\n  function start(resume) {\n    !resume && cancel();\n    startTime = now() - (resume ? rate * interval : 0);\n    paused = false;\n    raf(update);\n  }\n\n  function pause() {\n    paused = true;\n  }\n\n  function rewind() {\n    startTime = now();\n    rate = 0;\n\n    if (onUpdate) {\n      onUpdate(rate);\n    }\n  }\n\n  function cancel() {\n    id && cancelAnimationFrame(id);\n    rate = 0;\n    id = 0;\n    paused = true;\n  }\n\n  function set(time) {\n    interval = time;\n  }\n\n  function isPaused() {\n    return paused;\n  }\n\n  return {\n    start: start,\n    rewind: rewind,\n    pause: pause,\n    cancel: cancel,\n    set: set,\n    isPaused: isPaused\n  };\n}\n\nfunction State(initialState) {\n  var state = initialState;\n\n  function set(value) {\n    state = value;\n  }\n\n  function is(states) {\n    return includes(toArray(states), state);\n  }\n\n  return {\n    set: set,\n    is: is\n  };\n}\n\nfunction Throttle(func, duration) {\n  var interval;\n\n  function throttled() {\n    if (!interval) {\n      interval = RequestInterval(duration || 0, function () {\n        func();\n        interval = null;\n      }, null, 1);\n      interval.start();\n    }\n  }\n\n  return throttled;\n}\n\nfunction Media(Splide2, Components2, options) {\n  var state = Splide2.state;\n  var breakpoints = options.breakpoints || {};\n  var reducedMotion = options.reducedMotion || {};\n  var binder = EventBinder();\n  var queries = [];\n\n  function setup() {\n    var isMin = options.mediaQuery === \"min\";\n    ownKeys(breakpoints).sort(function (n, m) {\n      return isMin ? +n - +m : +m - +n;\n    }).forEach(function (key) {\n      register(breakpoints[key], \"(\" + (isMin ? \"min\" : \"max\") + \"-width:\" + key + \"px)\");\n    });\n    register(reducedMotion, MEDIA_PREFERS_REDUCED_MOTION);\n    update();\n  }\n\n  function destroy(completely) {\n    if (completely) {\n      binder.destroy();\n    }\n  }\n\n  function register(options2, query) {\n    var queryList = matchMedia(query);\n    binder.bind(queryList, \"change\", update);\n    queries.push([options2, queryList]);\n  }\n\n  function update() {\n    var destroyed = state.is(DESTROYED);\n    var direction = options.direction;\n    var merged = queries.reduce(function (merged2, entry) {\n      return merge(merged2, entry[1].matches ? entry[0] : {});\n    }, {});\n    omit(options);\n    set(merged);\n\n    if (options.destroy) {\n      Splide2.destroy(options.destroy === \"completely\");\n    } else if (destroyed) {\n      destroy(true);\n      Splide2.mount();\n    } else {\n      direction !== options.direction && Splide2.refresh();\n    }\n  }\n\n  function reduce(enable) {\n    if (matchMedia(MEDIA_PREFERS_REDUCED_MOTION).matches) {\n      enable ? merge(options, reducedMotion) : omit(options, ownKeys(reducedMotion));\n    }\n  }\n\n  function set(opts, user) {\n    merge(options, opts);\n    user && merge(Object.getPrototypeOf(options), opts);\n\n    if (!state.is(CREATED)) {\n      Splide2.emit(EVENT_UPDATED, options);\n    }\n  }\n\n  return {\n    setup: setup,\n    destroy: destroy,\n    reduce: reduce,\n    set: set\n  };\n}\n\nvar ARROW = \"Arrow\";\nvar ARROW_LEFT = ARROW + \"Left\";\nvar ARROW_RIGHT = ARROW + \"Right\";\nvar ARROW_UP = ARROW + \"Up\";\nvar ARROW_DOWN = ARROW + \"Down\";\nvar LTR = \"ltr\";\nvar RTL = \"rtl\";\nvar TTB = \"ttb\";\nvar ORIENTATION_MAP = {\n  width: [\"height\"],\n  left: [\"top\", \"right\"],\n  right: [\"bottom\", \"left\"],\n  x: [\"y\"],\n  X: [\"Y\"],\n  Y: [\"X\"],\n  ArrowLeft: [ARROW_UP, ARROW_RIGHT],\n  ArrowRight: [ARROW_DOWN, ARROW_LEFT]\n};\n\nfunction Direction(Splide2, Components2, options) {\n  function resolve(prop, axisOnly, direction) {\n    direction = direction || options.direction;\n    var index = direction === RTL && !axisOnly ? 1 : direction === TTB ? 0 : -1;\n    return ORIENTATION_MAP[prop] && ORIENTATION_MAP[prop][index] || prop.replace(/width|left|right/i, function (match, offset) {\n      var replacement = ORIENTATION_MAP[match.toLowerCase()][index] || match;\n      return offset > 0 ? replacement.charAt(0).toUpperCase() + replacement.slice(1) : replacement;\n    });\n  }\n\n  function orient(value) {\n    return value * (options.direction === RTL ? 1 : -1);\n  }\n\n  return {\n    resolve: resolve,\n    orient: orient\n  };\n}\n\nvar ROLE = \"role\";\nvar TAB_INDEX = \"tabindex\";\nvar DISABLED = \"disabled\";\nvar ARIA_PREFIX = \"aria-\";\nvar ARIA_CONTROLS = ARIA_PREFIX + \"controls\";\nvar ARIA_CURRENT = ARIA_PREFIX + \"current\";\nvar ARIA_SELECTED = ARIA_PREFIX + \"selected\";\nvar ARIA_LABEL = ARIA_PREFIX + \"label\";\nvar ARIA_LABELLEDBY = ARIA_PREFIX + \"labelledby\";\nvar ARIA_HIDDEN = ARIA_PREFIX + \"hidden\";\nvar ARIA_ORIENTATION = ARIA_PREFIX + \"orientation\";\nvar ARIA_ROLEDESCRIPTION = ARIA_PREFIX + \"roledescription\";\nvar ARIA_LIVE = ARIA_PREFIX + \"live\";\nvar ARIA_RELEVANT = ARIA_PREFIX + \"relevant\";\nvar ALL_ATTRIBUTES = [ROLE, TAB_INDEX, DISABLED, ARIA_CONTROLS, ARIA_CURRENT, ARIA_LABEL, ARIA_LABELLEDBY, ARIA_HIDDEN, ARIA_ORIENTATION, ARIA_ROLEDESCRIPTION];\nvar CLASS_ROOT = PROJECT_CODE;\nvar CLASS_TRACK = PROJECT_CODE + \"__track\";\nvar CLASS_LIST = PROJECT_CODE + \"__list\";\nvar CLASS_SLIDE = PROJECT_CODE + \"__slide\";\nvar CLASS_CLONE = CLASS_SLIDE + \"--clone\";\nvar CLASS_CONTAINER = CLASS_SLIDE + \"__container\";\nvar CLASS_ARROWS = PROJECT_CODE + \"__arrows\";\nvar CLASS_ARROW = PROJECT_CODE + \"__arrow\";\nvar CLASS_ARROW_PREV = CLASS_ARROW + \"--prev\";\nvar CLASS_ARROW_NEXT = CLASS_ARROW + \"--next\";\nvar CLASS_PAGINATION = PROJECT_CODE + \"__pagination\";\nvar CLASS_PAGINATION_PAGE = CLASS_PAGINATION + \"__page\";\nvar CLASS_PROGRESS = PROJECT_CODE + \"__progress\";\nvar CLASS_PROGRESS_BAR = CLASS_PROGRESS + \"__bar\";\nvar CLASS_TOGGLE = PROJECT_CODE + \"__toggle\";\nvar CLASS_TOGGLE_PLAY = CLASS_TOGGLE + \"__play\";\nvar CLASS_TOGGLE_PAUSE = CLASS_TOGGLE + \"__pause\";\nvar CLASS_SPINNER = PROJECT_CODE + \"__spinner\";\nvar CLASS_SR = PROJECT_CODE + \"__sr\";\nvar CLASS_INITIALIZED = \"is-initialized\";\nvar CLASS_ACTIVE = \"is-active\";\nvar CLASS_PREV = \"is-prev\";\nvar CLASS_NEXT = \"is-next\";\nvar CLASS_VISIBLE = \"is-visible\";\nvar CLASS_LOADING = \"is-loading\";\nvar CLASS_FOCUS_IN = \"is-focus-in\";\nvar STATUS_CLASSES = [CLASS_ACTIVE, CLASS_VISIBLE, CLASS_PREV, CLASS_NEXT, CLASS_LOADING, CLASS_FOCUS_IN];\nvar CLASSES = {\n  slide: CLASS_SLIDE,\n  clone: CLASS_CLONE,\n  arrows: CLASS_ARROWS,\n  arrow: CLASS_ARROW,\n  prev: CLASS_ARROW_PREV,\n  next: CLASS_ARROW_NEXT,\n  pagination: CLASS_PAGINATION,\n  page: CLASS_PAGINATION_PAGE,\n  spinner: CLASS_SPINNER\n};\n\nfunction closest(from, selector) {\n  if (isFunction(from.closest)) {\n    return from.closest(selector);\n  }\n\n  var elm = from;\n\n  while (elm && elm.nodeType === 1) {\n    if (matches(elm, selector)) {\n      break;\n    }\n\n    elm = elm.parentElement;\n  }\n\n  return elm;\n}\n\nvar FRICTION = 5;\nvar LOG_INTERVAL = 200;\nvar POINTER_DOWN_EVENTS = \"touchstart mousedown\";\nvar POINTER_MOVE_EVENTS = \"touchmove mousemove\";\nvar POINTER_UP_EVENTS = \"touchend touchcancel mouseup\";\n\nfunction Elements(Splide2, Components2, options) {\n  var _EventInterface = EventInterface(Splide2),\n      on = _EventInterface.on,\n      bind = _EventInterface.bind;\n\n  var root = Splide2.root;\n  var i18n = options.i18n;\n  var elements = {};\n  var slides = [];\n  var rootClasses = [];\n  var trackClasses = [];\n  var track;\n  var list;\n  var isUsingKey;\n\n  function setup() {\n    collect();\n    init();\n    update();\n  }\n\n  function mount() {\n    on(EVENT_REFRESH, destroy);\n    on(EVENT_REFRESH, setup);\n    on(EVENT_UPDATED, update);\n    bind(document, POINTER_DOWN_EVENTS + \" keydown\", function (e) {\n      isUsingKey = e.type === \"keydown\";\n    }, {\n      capture: true\n    });\n    bind(root, \"focusin\", function () {\n      toggleClass(root, CLASS_FOCUS_IN, !!isUsingKey);\n    });\n  }\n\n  function destroy(completely) {\n    var attrs = ALL_ATTRIBUTES.concat(\"style\");\n    empty(slides);\n    removeClass(root, rootClasses);\n    removeClass(track, trackClasses);\n    removeAttribute([track, list], attrs);\n    removeAttribute(root, completely ? attrs : [\"style\", ARIA_ROLEDESCRIPTION]);\n  }\n\n  function update() {\n    removeClass(root, rootClasses);\n    removeClass(track, trackClasses);\n    rootClasses = getClasses(CLASS_ROOT);\n    trackClasses = getClasses(CLASS_TRACK);\n    addClass(root, rootClasses);\n    addClass(track, trackClasses);\n    setAttribute(root, ARIA_LABEL, options.label);\n    setAttribute(root, ARIA_LABELLEDBY, options.labelledby);\n  }\n\n  function collect() {\n    track = find(\".\" + CLASS_TRACK);\n    list = child(track, \".\" + CLASS_LIST);\n    assert(track && list, \"A track/list element is missing.\");\n    push(slides, children(list, \".\" + CLASS_SLIDE + \":not(.\" + CLASS_CLONE + \")\"));\n    forOwn({\n      arrows: CLASS_ARROWS,\n      pagination: CLASS_PAGINATION,\n      prev: CLASS_ARROW_PREV,\n      next: CLASS_ARROW_NEXT,\n      bar: CLASS_PROGRESS_BAR,\n      toggle: CLASS_TOGGLE\n    }, function (className, key) {\n      elements[key] = find(\".\" + className);\n    });\n    assign(elements, {\n      root: root,\n      track: track,\n      list: list,\n      slides: slides\n    });\n  }\n\n  function init() {\n    var id = root.id || uniqueId(PROJECT_CODE);\n    var role = options.role;\n    root.id = id;\n    track.id = track.id || id + \"-track\";\n    list.id = list.id || id + \"-list\";\n\n    if (!getAttribute(root, ROLE) && root.tagName !== \"SECTION\" && role) {\n      setAttribute(root, ROLE, role);\n    }\n\n    setAttribute(root, ARIA_ROLEDESCRIPTION, i18n.carousel);\n    setAttribute(list, ROLE, \"presentation\");\n  }\n\n  function find(selector) {\n    var elm = query(root, selector);\n    return elm && closest(elm, \".\" + CLASS_ROOT) === root ? elm : void 0;\n  }\n\n  function getClasses(base) {\n    return [base + \"--\" + options.type, base + \"--\" + options.direction, options.drag && base + \"--draggable\", options.isNavigation && base + \"--nav\", base === CLASS_ROOT && CLASS_ACTIVE];\n  }\n\n  return assign(elements, {\n    setup: setup,\n    mount: mount,\n    destroy: destroy\n  });\n}\n\nvar SLIDE = \"slide\";\nvar LOOP = \"loop\";\nvar FADE = \"fade\";\n\nfunction Slide$1(Splide2, index, slideIndex, slide) {\n  var event = EventInterface(Splide2);\n  var on = event.on,\n      emit = event.emit,\n      bind = event.bind;\n  var Components = Splide2.Components,\n      root = Splide2.root,\n      options = Splide2.options;\n  var isNavigation = options.isNavigation,\n      updateOnMove = options.updateOnMove,\n      i18n = options.i18n,\n      pagination = options.pagination,\n      slideFocus = options.slideFocus;\n  var resolve = Components.Direction.resolve;\n  var styles = getAttribute(slide, \"style\");\n  var label = getAttribute(slide, ARIA_LABEL);\n  var isClone = slideIndex > -1;\n  var container = child(slide, \".\" + CLASS_CONTAINER);\n  var focusableNodes = queryAll(slide, options.focusableNodes || \"\");\n  var destroyed;\n\n  function mount() {\n    if (!isClone) {\n      slide.id = root.id + \"-slide\" + pad(index + 1);\n      setAttribute(slide, ROLE, pagination ? \"tabpanel\" : \"group\");\n      setAttribute(slide, ARIA_ROLEDESCRIPTION, i18n.slide);\n      setAttribute(slide, ARIA_LABEL, label || format(i18n.slideLabel, [index + 1, Splide2.length]));\n    }\n\n    listen();\n  }\n\n  function listen() {\n    bind(slide, \"click\", apply(emit, EVENT_CLICK, self));\n    bind(slide, \"keydown\", apply(emit, EVENT_SLIDE_KEYDOWN, self));\n    on([EVENT_MOVED, EVENT_SHIFTED, EVENT_SCROLLED], update);\n    on(EVENT_NAVIGATION_MOUNTED, initNavigation);\n\n    if (updateOnMove) {\n      on(EVENT_MOVE, onMove);\n    }\n  }\n\n  function destroy() {\n    destroyed = true;\n    event.destroy();\n    removeClass(slide, STATUS_CLASSES);\n    removeAttribute(slide, ALL_ATTRIBUTES);\n    setAttribute(slide, \"style\", styles);\n    setAttribute(slide, ARIA_LABEL, label || \"\");\n  }\n\n  function initNavigation() {\n    var controls = Splide2.splides.map(function (target) {\n      var Slide2 = target.splide.Components.Slides.getAt(index);\n      return Slide2 ? Slide2.slide.id : \"\";\n    }).join(\" \");\n    setAttribute(slide, ARIA_LABEL, format(i18n.slideX, (isClone ? slideIndex : index) + 1));\n    setAttribute(slide, ARIA_CONTROLS, controls);\n    setAttribute(slide, ROLE, slideFocus ? \"button\" : \"\");\n    slideFocus && removeAttribute(slide, ARIA_ROLEDESCRIPTION);\n  }\n\n  function onMove() {\n    if (!destroyed) {\n      update();\n    }\n  }\n\n  function update() {\n    if (!destroyed) {\n      var curr = Splide2.index;\n      updateActivity();\n      updateVisibility();\n      toggleClass(slide, CLASS_PREV, index === curr - 1);\n      toggleClass(slide, CLASS_NEXT, index === curr + 1);\n    }\n  }\n\n  function updateActivity() {\n    var active = isActive();\n\n    if (active !== hasClass(slide, CLASS_ACTIVE)) {\n      toggleClass(slide, CLASS_ACTIVE, active);\n      setAttribute(slide, ARIA_CURRENT, isNavigation && active || \"\");\n      emit(active ? EVENT_ACTIVE : EVENT_INACTIVE, self);\n    }\n  }\n\n  function updateVisibility() {\n    var visible = isVisible();\n    var hidden = !visible && (!isActive() || isClone);\n\n    if (!Splide2.state.is([MOVING, SCROLLING])) {\n      setAttribute(slide, ARIA_HIDDEN, hidden || \"\");\n    }\n\n    setAttribute(focusableNodes, TAB_INDEX, hidden ? -1 : \"\");\n\n    if (slideFocus) {\n      setAttribute(slide, TAB_INDEX, hidden ? -1 : 0);\n    }\n\n    if (visible !== hasClass(slide, CLASS_VISIBLE)) {\n      toggleClass(slide, CLASS_VISIBLE, visible);\n      emit(visible ? EVENT_VISIBLE : EVENT_HIDDEN, self);\n    }\n\n    if (!visible && document.activeElement === slide) {\n      var Slide2 = Components.Slides.getAt(Splide2.index);\n      Slide2 && focus(Slide2.slide);\n    }\n  }\n\n  function style$1(prop, value, useContainer) {\n    style(useContainer && container || slide, prop, value);\n  }\n\n  function isActive() {\n    var curr = Splide2.index;\n    return curr === index || options.cloneStatus && curr === slideIndex;\n  }\n\n  function isVisible() {\n    if (Splide2.is(FADE)) {\n      return isActive();\n    }\n\n    var trackRect = rect(Components.Elements.track);\n    var slideRect = rect(slide);\n    var left = resolve(\"left\");\n    var right = resolve(\"right\");\n    return floor(trackRect[left]) <= ceil(slideRect[left]) && floor(slideRect[right]) <= ceil(trackRect[right]);\n  }\n\n  function isWithin(from, distance) {\n    var diff = abs(from - index);\n\n    if (!isClone && (options.rewind || Splide2.is(LOOP))) {\n      diff = min(diff, Splide2.length - diff);\n    }\n\n    return diff <= distance;\n  }\n\n  var self = {\n    index: index,\n    slideIndex: slideIndex,\n    slide: slide,\n    container: container,\n    isClone: isClone,\n    mount: mount,\n    destroy: destroy,\n    update: update,\n    style: style$1,\n    isWithin: isWithin\n  };\n  return self;\n}\n\nfunction Slides(Splide2, Components2, options) {\n  var _EventInterface2 = EventInterface(Splide2),\n      on = _EventInterface2.on,\n      emit = _EventInterface2.emit,\n      bind = _EventInterface2.bind;\n\n  var _Components2$Elements = Components2.Elements,\n      slides = _Components2$Elements.slides,\n      list = _Components2$Elements.list;\n  var Slides2 = [];\n\n  function mount() {\n    init();\n    on(EVENT_REFRESH, destroy);\n    on(EVENT_REFRESH, init);\n    on([EVENT_MOUNTED, EVENT_REFRESH], function () {\n      Slides2.sort(function (Slide1, Slide2) {\n        return Slide1.index - Slide2.index;\n      });\n    });\n  }\n\n  function init() {\n    slides.forEach(function (slide, index) {\n      register(slide, index, -1);\n    });\n  }\n\n  function destroy() {\n    forEach$1(function (Slide2) {\n      Slide2.destroy();\n    });\n    empty(Slides2);\n  }\n\n  function update() {\n    forEach$1(function (Slide2) {\n      Slide2.update();\n    });\n  }\n\n  function register(slide, index, slideIndex) {\n    var object = Slide$1(Splide2, index, slideIndex, slide);\n    object.mount();\n    Slides2.push(object);\n  }\n\n  function get(excludeClones) {\n    return excludeClones ? filter(function (Slide2) {\n      return !Slide2.isClone;\n    }) : Slides2;\n  }\n\n  function getIn(page) {\n    var Controller = Components2.Controller;\n    var index = Controller.toIndex(page);\n    var max = Controller.hasFocus() ? 1 : options.perPage;\n    return filter(function (Slide2) {\n      return between(Slide2.index, index, index + max - 1);\n    });\n  }\n\n  function getAt(index) {\n    return filter(index)[0];\n  }\n\n  function add(items, index) {\n    forEach(items, function (slide) {\n      if (isString(slide)) {\n        slide = parseHtml(slide);\n      }\n\n      if (isHTMLElement(slide)) {\n        var ref = slides[index];\n        ref ? before(slide, ref) : append(list, slide);\n        addClass(slide, options.classes.slide);\n        observeImages(slide, apply(emit, EVENT_RESIZE));\n      }\n    });\n    emit(EVENT_REFRESH);\n  }\n\n  function remove$1(matcher) {\n    remove(filter(matcher).map(function (Slide2) {\n      return Slide2.slide;\n    }));\n    emit(EVENT_REFRESH);\n  }\n\n  function forEach$1(iteratee, excludeClones) {\n    get(excludeClones).forEach(iteratee);\n  }\n\n  function filter(matcher) {\n    return Slides2.filter(isFunction(matcher) ? matcher : function (Slide2) {\n      return isString(matcher) ? matches(Slide2.slide, matcher) : includes(toArray(matcher), Slide2.index);\n    });\n  }\n\n  function style(prop, value, useContainer) {\n    forEach$1(function (Slide2) {\n      Slide2.style(prop, value, useContainer);\n    });\n  }\n\n  function observeImages(elm, callback) {\n    var images = queryAll(elm, \"img\");\n    var length = images.length;\n\n    if (length) {\n      images.forEach(function (img) {\n        bind(img, \"load error\", function () {\n          if (! --length) {\n            callback();\n          }\n        });\n      });\n    } else {\n      callback();\n    }\n  }\n\n  function getLength(excludeClones) {\n    return excludeClones ? slides.length : Slides2.length;\n  }\n\n  function isEnough() {\n    return Slides2.length > options.perPage;\n  }\n\n  return {\n    mount: mount,\n    destroy: destroy,\n    update: update,\n    register: register,\n    get: get,\n    getIn: getIn,\n    getAt: getAt,\n    add: add,\n    remove: remove$1,\n    forEach: forEach$1,\n    filter: filter,\n    style: style,\n    getLength: getLength,\n    isEnough: isEnough\n  };\n}\n\nfunction Layout(Splide2, Components2, options) {\n  var _EventInterface3 = EventInterface(Splide2),\n      on = _EventInterface3.on,\n      bind = _EventInterface3.bind,\n      emit = _EventInterface3.emit;\n\n  var Slides = Components2.Slides;\n  var resolve = Components2.Direction.resolve;\n  var _Components2$Elements2 = Components2.Elements,\n      root = _Components2$Elements2.root,\n      track = _Components2$Elements2.track,\n      list = _Components2$Elements2.list;\n  var getAt = Slides.getAt,\n      styleSlides = Slides.style;\n  var vertical;\n  var rootRect;\n\n  function mount() {\n    init();\n    bind(window, \"resize load\", Throttle(apply(emit, EVENT_RESIZE)));\n    on([EVENT_UPDATED, EVENT_REFRESH], init);\n    on(EVENT_RESIZE, resize);\n  }\n\n  function init() {\n    rootRect = null;\n    vertical = options.direction === TTB;\n    style(root, \"maxWidth\", unit(options.width));\n    style(track, resolve(\"paddingLeft\"), cssPadding(false));\n    style(track, resolve(\"paddingRight\"), cssPadding(true));\n    resize();\n  }\n\n  function resize() {\n    var newRect = rect(root);\n\n    if (!rootRect || rootRect.width !== newRect.width || rootRect.height !== newRect.height) {\n      style(track, \"height\", cssTrackHeight());\n      styleSlides(resolve(\"marginRight\"), unit(options.gap));\n      styleSlides(\"width\", cssSlideWidth());\n      styleSlides(\"height\", cssSlideHeight(), true);\n      rootRect = newRect;\n      emit(EVENT_RESIZED);\n    }\n  }\n\n  function cssPadding(right) {\n    var padding = options.padding;\n    var prop = resolve(right ? \"right\" : \"left\");\n    return padding && unit(padding[prop] || (isObject(padding) ? 0 : padding)) || \"0px\";\n  }\n\n  function cssTrackHeight() {\n    var height = \"\";\n\n    if (vertical) {\n      height = cssHeight();\n      assert(height, \"height or heightRatio is missing.\");\n      height = \"calc(\" + height + \" - \" + cssPadding(false) + \" - \" + cssPadding(true) + \")\";\n    }\n\n    return height;\n  }\n\n  function cssHeight() {\n    return unit(options.height || rect(list).width * options.heightRatio);\n  }\n\n  function cssSlideWidth() {\n    return options.autoWidth ? null : unit(options.fixedWidth) || (vertical ? \"\" : cssSlideSize());\n  }\n\n  function cssSlideHeight() {\n    return unit(options.fixedHeight) || (vertical ? options.autoHeight ? null : cssSlideSize() : cssHeight());\n  }\n\n  function cssSlideSize() {\n    var gap = unit(options.gap);\n    return \"calc((100%\" + (gap && \" + \" + gap) + \")/\" + (options.perPage || 1) + (gap && \" - \" + gap) + \")\";\n  }\n\n  function listSize() {\n    return rect(list)[resolve(\"width\")];\n  }\n\n  function slideSize(index, withoutGap) {\n    var Slide = getAt(index || 0);\n    return Slide ? rect(Slide.slide)[resolve(\"width\")] + (withoutGap ? 0 : getGap()) : 0;\n  }\n\n  function totalSize(index, withoutGap) {\n    var Slide = getAt(index);\n\n    if (Slide) {\n      var right = rect(Slide.slide)[resolve(\"right\")];\n      var left = rect(list)[resolve(\"left\")];\n      return abs(right - left) + (withoutGap ? 0 : getGap());\n    }\n\n    return 0;\n  }\n\n  function sliderSize() {\n    return totalSize(Splide2.length - 1, true) - totalSize(-1, true);\n  }\n\n  function getGap() {\n    var Slide = getAt(0);\n    return Slide && parseFloat(style(Slide.slide, resolve(\"marginRight\"))) || 0;\n  }\n\n  function getPadding(right) {\n    return parseFloat(style(track, resolve(\"padding\" + (right ? \"Right\" : \"Left\")))) || 0;\n  }\n\n  return {\n    mount: mount,\n    listSize: listSize,\n    slideSize: slideSize,\n    sliderSize: sliderSize,\n    totalSize: totalSize,\n    getPadding: getPadding\n  };\n}\n\nvar MULTIPLIER = 2;\n\nfunction Clones(Splide2, Components2, options) {\n  var _EventInterface4 = EventInterface(Splide2),\n      on = _EventInterface4.on,\n      emit = _EventInterface4.emit;\n\n  var Elements = Components2.Elements,\n      Slides = Components2.Slides;\n  var resolve = Components2.Direction.resolve;\n  var clones = [];\n  var cloneCount;\n\n  function mount() {\n    init();\n    on(EVENT_REFRESH, destroy);\n    on(EVENT_REFRESH, init);\n    on([EVENT_UPDATED, EVENT_RESIZE], observe);\n  }\n\n  function init() {\n    if (cloneCount = computeCloneCount()) {\n      generate(cloneCount);\n      emit(EVENT_RESIZE);\n    }\n  }\n\n  function destroy() {\n    remove(clones);\n    empty(clones);\n  }\n\n  function observe() {\n    if (cloneCount < computeCloneCount()) {\n      emit(EVENT_REFRESH);\n    }\n  }\n\n  function generate(count) {\n    var slides = Slides.get().slice();\n    var length = slides.length;\n\n    if (length) {\n      while (slides.length < count) {\n        push(slides, slides);\n      }\n\n      push(slides.slice(-count), slides.slice(0, count)).forEach(function (Slide, index) {\n        var isHead = index < count;\n        var clone = cloneDeep(Slide.slide, index);\n        isHead ? before(clone, slides[0].slide) : append(Elements.list, clone);\n        push(clones, clone);\n        Slides.register(clone, index - count + (isHead ? 0 : length), Slide.index);\n      });\n    }\n  }\n\n  function cloneDeep(elm, index) {\n    var clone = elm.cloneNode(true);\n    addClass(clone, options.classes.clone);\n    clone.id = Splide2.root.id + \"-clone\" + pad(index + 1);\n    return clone;\n  }\n\n  function computeCloneCount() {\n    var clones2 = options.clones;\n\n    if (!Splide2.is(LOOP)) {\n      clones2 = 0;\n    } else if (!clones2) {\n      var fixedSize = options[resolve(\"fixedWidth\")] && Components2.Layout.slideSize(0);\n      var fixedCount = fixedSize && ceil(rect(Elements.track)[resolve(\"width\")] / fixedSize);\n      clones2 = fixedCount || options[resolve(\"autoWidth\")] && Splide2.length || options.perPage * MULTIPLIER;\n    }\n\n    return clones2;\n  }\n\n  return {\n    mount: mount,\n    destroy: destroy\n  };\n}\n\nfunction Move(Splide2, Components2, options) {\n  var _EventInterface5 = EventInterface(Splide2),\n      on = _EventInterface5.on,\n      emit = _EventInterface5.emit;\n\n  var set = Splide2.state.set;\n  var _Components2$Layout = Components2.Layout,\n      slideSize = _Components2$Layout.slideSize,\n      getPadding = _Components2$Layout.getPadding,\n      totalSize = _Components2$Layout.totalSize,\n      listSize = _Components2$Layout.listSize,\n      sliderSize = _Components2$Layout.sliderSize;\n  var _Components2$Directio = Components2.Direction,\n      resolve = _Components2$Directio.resolve,\n      orient = _Components2$Directio.orient;\n  var _Components2$Elements3 = Components2.Elements,\n      list = _Components2$Elements3.list,\n      track = _Components2$Elements3.track;\n  var Transition;\n\n  function mount() {\n    Transition = Components2.Transition;\n    on([EVENT_MOUNTED, EVENT_RESIZED, EVENT_UPDATED, EVENT_REFRESH], reposition);\n  }\n\n  function reposition() {\n    if (!Components2.Controller.isBusy()) {\n      Components2.Scroll.cancel();\n      jump(Splide2.index);\n      Components2.Slides.update();\n    }\n  }\n\n  function move(dest, index, prev, callback) {\n    var position = getPosition();\n\n    if (dest !== index && canShift(dest > index)) {\n      cancel();\n      translate(shift(position, dest > index), true);\n    }\n\n    set(MOVING);\n    emit(EVENT_MOVE, index, prev, dest);\n    Transition.start(index, function () {\n      set(IDLE);\n      emit(EVENT_MOVED, index, prev, dest);\n      callback && callback();\n    });\n  }\n\n  function jump(index) {\n    translate(toPosition(index, true));\n  }\n\n  function translate(position, preventLoop) {\n    if (!Splide2.is(FADE)) {\n      var destination = preventLoop ? position : loop(position);\n      style(list, \"transform\", \"translate\" + resolve(\"X\") + \"(\" + destination + \"px)\");\n      position !== destination && emit(EVENT_SHIFTED);\n    }\n  }\n\n  function loop(position) {\n    if (Splide2.is(LOOP)) {\n      var diff = orient(position - getPosition());\n      var exceededMin = exceededLimit(false, position) && diff < 0;\n      var exceededMax = exceededLimit(true, position) && diff > 0;\n\n      if (exceededMin || exceededMax) {\n        position = shift(position, exceededMax);\n      }\n    }\n\n    return position;\n  }\n\n  function shift(position, backwards) {\n    var excess = position - getLimit(backwards);\n    var size = sliderSize();\n    position -= orient(size * (ceil(abs(excess) / size) || 1)) * (backwards ? 1 : -1);\n    return position;\n  }\n\n  function cancel() {\n    translate(getPosition());\n    Transition.cancel();\n  }\n\n  function toIndex(position) {\n    var Slides = Components2.Slides.get();\n    var index = 0;\n    var minDistance = Infinity;\n\n    for (var i = 0; i < Slides.length; i++) {\n      var slideIndex = Slides[i].index;\n      var distance = abs(toPosition(slideIndex, true) - position);\n\n      if (distance <= minDistance) {\n        minDistance = distance;\n        index = slideIndex;\n      } else {\n        break;\n      }\n    }\n\n    return index;\n  }\n\n  function toPosition(index, trimming) {\n    var position = orient(totalSize(index - 1) - offset(index));\n    return trimming ? trim(position) : position;\n  }\n\n  function getPosition() {\n    var left = resolve(\"left\");\n    return rect(list)[left] - rect(track)[left] + orient(getPadding(false));\n  }\n\n  function trim(position) {\n    if (options.trimSpace && Splide2.is(SLIDE)) {\n      position = clamp(position, 0, orient(sliderSize() - listSize()));\n    }\n\n    return position;\n  }\n\n  function offset(index) {\n    var focus = options.focus;\n    return focus === \"center\" ? (listSize() - slideSize(index, true)) / 2 : +focus * slideSize(index) || 0;\n  }\n\n  function getLimit(max) {\n    return toPosition(max ? Components2.Controller.getEnd() : 0, !!options.trimSpace);\n  }\n\n  function canShift(backwards) {\n    var shifted = orient(shift(getPosition(), backwards));\n    return backwards ? shifted >= 0 : shifted <= list[\"scroll\" + resolve(\"Width\")] - rect(track)[resolve(\"width\")];\n  }\n\n  function exceededLimit(max, position) {\n    position = isUndefined(position) ? getPosition() : position;\n    var exceededMin = max !== true && orient(position) < orient(getLimit(false));\n    var exceededMax = max !== false && orient(position) > orient(getLimit(true));\n    return exceededMin || exceededMax;\n  }\n\n  return {\n    mount: mount,\n    move: move,\n    jump: jump,\n    translate: translate,\n    shift: shift,\n    cancel: cancel,\n    toIndex: toIndex,\n    toPosition: toPosition,\n    getPosition: getPosition,\n    getLimit: getLimit,\n    exceededLimit: exceededLimit,\n    reposition: reposition\n  };\n}\n\nfunction Controller(Splide2, Components2, options) {\n  var _EventInterface6 = EventInterface(Splide2),\n      on = _EventInterface6.on;\n\n  var Move = Components2.Move;\n  var getPosition = Move.getPosition,\n      getLimit = Move.getLimit,\n      toPosition = Move.toPosition;\n  var _Components2$Slides = Components2.Slides,\n      isEnough = _Components2$Slides.isEnough,\n      getLength = _Components2$Slides.getLength;\n  var isLoop = Splide2.is(LOOP);\n  var isSlide = Splide2.is(SLIDE);\n  var getNext = apply(getAdjacent, false);\n  var getPrev = apply(getAdjacent, true);\n  var currIndex = options.start || 0;\n  var prevIndex = currIndex;\n  var slideCount;\n  var perMove;\n  var perPage;\n\n  function mount() {\n    init();\n    on([EVENT_UPDATED, EVENT_REFRESH], init);\n  }\n\n  function init() {\n    slideCount = getLength(true);\n    perMove = options.perMove;\n    perPage = options.perPage;\n    var index = clamp(currIndex, 0, slideCount - 1);\n\n    if (index !== currIndex) {\n      currIndex = index;\n      Move.reposition();\n    }\n  }\n\n  function go(control, allowSameIndex, callback) {\n    if (!isBusy()) {\n      var dest = parse(control);\n      var index = loop(dest);\n\n      if (index > -1 && (allowSameIndex || index !== currIndex)) {\n        setIndex(index);\n        Move.move(dest, index, prevIndex, callback);\n      }\n    }\n  }\n\n  function scroll(destination, duration, snap, callback) {\n    Components2.Scroll.scroll(destination, duration, snap, function () {\n      setIndex(loop(Move.toIndex(Move.getPosition())));\n      callback && callback();\n    });\n  }\n\n  function parse(control) {\n    var index = currIndex;\n\n    if (isString(control)) {\n      var _ref = control.match(/([+\\-<>])(\\d+)?/) || [],\n          indicator = _ref[1],\n          number = _ref[2];\n\n      if (indicator === \"+\" || indicator === \"-\") {\n        index = computeDestIndex(currIndex + +(\"\" + indicator + (+number || 1)), currIndex);\n      } else if (indicator === \">\") {\n        index = number ? toIndex(+number) : getNext(true);\n      } else if (indicator === \"<\") {\n        index = getPrev(true);\n      }\n    } else {\n      index = isLoop ? control : clamp(control, 0, getEnd());\n    }\n\n    return index;\n  }\n\n  function getAdjacent(prev, destination) {\n    var number = perMove || (hasFocus() ? 1 : perPage);\n    var dest = computeDestIndex(currIndex + number * (prev ? -1 : 1), currIndex, !(perMove || hasFocus()));\n\n    if (dest === -1 && isSlide) {\n      if (!approximatelyEqual(getPosition(), getLimit(!prev), 1)) {\n        return prev ? 0 : getEnd();\n      }\n    }\n\n    return destination ? dest : loop(dest);\n  }\n\n  function computeDestIndex(dest, from, snapPage) {\n    if (isEnough()) {\n      var end = getEnd();\n      var index = computeMovableDestIndex(dest);\n\n      if (index !== dest) {\n        from = dest;\n        dest = index;\n        snapPage = false;\n      }\n\n      if (dest < 0 || dest > end) {\n        if (between(0, dest, from, true) || between(end, from, dest, true)) {\n          dest = toIndex(toPage(dest));\n        } else {\n          if (isLoop) {\n            dest = snapPage ? dest < 0 ? -(slideCount % perPage || perPage) : slideCount : dest;\n          } else if (options.rewind) {\n            dest = dest < 0 ? end : 0;\n          } else {\n            dest = -1;\n          }\n        }\n      } else {\n        if (snapPage && dest !== from) {\n          dest = toIndex(toPage(from) + (dest < from ? -1 : 1));\n        }\n      }\n    } else {\n      dest = -1;\n    }\n\n    return dest;\n  }\n\n  function computeMovableDestIndex(dest) {\n    if (isSlide && options.trimSpace === \"move\" && dest !== currIndex) {\n      var position = getPosition();\n\n      while (position === toPosition(dest, true) && between(dest, 0, Splide2.length - 1, !options.rewind)) {\n        dest < currIndex ? --dest : ++dest;\n      }\n    }\n\n    return dest;\n  }\n\n  function loop(index) {\n    return isLoop ? (index + slideCount) % slideCount || 0 : index;\n  }\n\n  function getEnd() {\n    return max(slideCount - (hasFocus() || isLoop && perMove ? 1 : perPage), 0);\n  }\n\n  function toIndex(page) {\n    return clamp(hasFocus() ? page : perPage * page, 0, getEnd());\n  }\n\n  function toPage(index) {\n    return hasFocus() ? index : floor((index >= getEnd() ? slideCount - 1 : index) / perPage);\n  }\n\n  function toDest(destination) {\n    var closest = Move.toIndex(destination);\n    return isSlide ? clamp(closest, 0, getEnd()) : closest;\n  }\n\n  function setIndex(index) {\n    if (index !== currIndex) {\n      prevIndex = currIndex;\n      currIndex = index;\n    }\n  }\n\n  function getIndex(prev) {\n    return prev ? prevIndex : currIndex;\n  }\n\n  function hasFocus() {\n    return !isUndefined(options.focus) || options.isNavigation;\n  }\n\n  function isBusy() {\n    return Splide2.state.is([MOVING, SCROLLING]) && !!options.waitForTransition;\n  }\n\n  return {\n    mount: mount,\n    go: go,\n    scroll: scroll,\n    getNext: getNext,\n    getPrev: getPrev,\n    getAdjacent: getAdjacent,\n    getEnd: getEnd,\n    setIndex: setIndex,\n    getIndex: getIndex,\n    toIndex: toIndex,\n    toPage: toPage,\n    toDest: toDest,\n    hasFocus: hasFocus,\n    isBusy: isBusy\n  };\n}\n\nvar XML_NAME_SPACE = \"http://www.w3.org/2000/svg\";\nvar PATH = \"m15.5 0.932-4.3 4.38 14.5 14.6-14.5 14.5 4.3 4.4 14.6-14.6 4.4-4.3-4.4-4.4-14.6-14.6z\";\nvar SIZE = 40;\n\nfunction Arrows(Splide2, Components2, options) {\n  var event = EventInterface(Splide2);\n  var on = event.on,\n      bind = event.bind,\n      emit = event.emit;\n  var classes = options.classes,\n      i18n = options.i18n;\n  var Elements = Components2.Elements,\n      Controller = Components2.Controller;\n  var userArrows = Elements.arrows,\n      track = Elements.track;\n  var wrapper = userArrows;\n  var prev = Elements.prev;\n  var next = Elements.next;\n  var created;\n  var wrapperClasses;\n  var arrows = {};\n\n  function mount() {\n    init();\n    on(EVENT_UPDATED, remount);\n  }\n\n  function remount() {\n    destroy();\n    mount();\n  }\n\n  function init() {\n    var enabled = options.arrows;\n\n    if (enabled && !(prev && next)) {\n      createArrows();\n    }\n\n    if (prev && next) {\n      assign(arrows, {\n        prev: prev,\n        next: next\n      });\n      display(wrapper, enabled ? \"\" : \"none\");\n      addClass(wrapper, wrapperClasses = CLASS_ARROWS + \"--\" + options.direction);\n\n      if (enabled) {\n        listen();\n        update();\n        setAttribute([prev, next], ARIA_CONTROLS, track.id);\n        emit(EVENT_ARROWS_MOUNTED, prev, next);\n      }\n    }\n  }\n\n  function destroy() {\n    event.destroy();\n    removeClass(wrapper, wrapperClasses);\n\n    if (created) {\n      remove(userArrows ? [prev, next] : wrapper);\n      prev = next = null;\n    } else {\n      removeAttribute([prev, next], ALL_ATTRIBUTES);\n    }\n  }\n\n  function listen() {\n    on([EVENT_MOVED, EVENT_REFRESH, EVENT_SCROLLED], update);\n    bind(next, \"click\", apply(go, \">\"));\n    bind(prev, \"click\", apply(go, \"<\"));\n  }\n\n  function go(control) {\n    Controller.go(control, true);\n  }\n\n  function createArrows() {\n    wrapper = userArrows || create(\"div\", classes.arrows);\n    prev = createArrow(true);\n    next = createArrow(false);\n    created = true;\n    append(wrapper, [prev, next]);\n    !userArrows && before(wrapper, track);\n  }\n\n  function createArrow(prev2) {\n    var arrow = \"<button class=\\\"\" + classes.arrow + \" \" + (prev2 ? classes.prev : classes.next) + \"\\\" type=\\\"button\\\"><svg xmlns=\\\"\" + XML_NAME_SPACE + \"\\\" viewBox=\\\"0 0 \" + SIZE + \" \" + SIZE + \"\\\" width=\\\"\" + SIZE + \"\\\" height=\\\"\" + SIZE + \"\\\" focusable=\\\"false\\\"><path d=\\\"\" + (options.arrowPath || PATH) + \"\\\" />\";\n    return parseHtml(arrow);\n  }\n\n  function update() {\n    var index = Splide2.index;\n    var prevIndex = Controller.getPrev();\n    var nextIndex = Controller.getNext();\n    var prevLabel = prevIndex > -1 && index < prevIndex ? i18n.last : i18n.prev;\n    var nextLabel = nextIndex > -1 && index > nextIndex ? i18n.first : i18n.next;\n    prev.disabled = prevIndex < 0;\n    next.disabled = nextIndex < 0;\n    setAttribute(prev, ARIA_LABEL, prevLabel);\n    setAttribute(next, ARIA_LABEL, nextLabel);\n    emit(EVENT_ARROWS_UPDATED, prev, next, prevIndex, nextIndex);\n  }\n\n  return {\n    arrows: arrows,\n    mount: mount,\n    destroy: destroy\n  };\n}\n\nvar INTERVAL_DATA_ATTRIBUTE = DATA_ATTRIBUTE + \"-interval\";\n\nfunction Autoplay(Splide2, Components2, options) {\n  var _EventInterface7 = EventInterface(Splide2),\n      on = _EventInterface7.on,\n      bind = _EventInterface7.bind,\n      emit = _EventInterface7.emit;\n\n  var interval = RequestInterval(options.interval, Splide2.go.bind(Splide2, \">\"), onAnimationFrame);\n  var isPaused = interval.isPaused;\n  var Elements = Components2.Elements,\n      _Components2$Elements4 = Components2.Elements,\n      root = _Components2$Elements4.root,\n      toggle = _Components2$Elements4.toggle;\n  var autoplay = options.autoplay;\n  var hovered;\n  var focused;\n  var stopped = autoplay === \"pause\";\n\n  function mount() {\n    if (autoplay) {\n      listen();\n      toggle && setAttribute(toggle, ARIA_CONTROLS, Elements.track.id);\n      stopped || play();\n      update();\n    }\n  }\n\n  function listen() {\n    if (options.pauseOnHover) {\n      bind(root, \"mouseenter mouseleave\", function (e) {\n        hovered = e.type === \"mouseenter\";\n        autoToggle();\n      });\n    }\n\n    if (options.pauseOnFocus) {\n      bind(root, \"focusin focusout\", function (e) {\n        focused = e.type === \"focusin\";\n        autoToggle();\n      });\n    }\n\n    if (toggle) {\n      bind(toggle, \"click\", function () {\n        stopped ? play() : pause(true);\n      });\n    }\n\n    on([EVENT_MOVE, EVENT_SCROLL, EVENT_REFRESH], interval.rewind);\n    on(EVENT_MOVE, onMove);\n  }\n\n  function play() {\n    if (isPaused() && Components2.Slides.isEnough()) {\n      interval.start(!options.resetProgress);\n      focused = hovered = stopped = false;\n      update();\n      emit(EVENT_AUTOPLAY_PLAY);\n    }\n  }\n\n  function pause(stop) {\n    if (stop === void 0) {\n      stop = true;\n    }\n\n    stopped = !!stop;\n    update();\n\n    if (!isPaused()) {\n      interval.pause();\n      emit(EVENT_AUTOPLAY_PAUSE);\n    }\n  }\n\n  function autoToggle() {\n    if (!stopped) {\n      hovered || focused ? pause(false) : play();\n    }\n  }\n\n  function update() {\n    if (toggle) {\n      toggleClass(toggle, CLASS_ACTIVE, !stopped);\n      setAttribute(toggle, ARIA_LABEL, options.i18n[stopped ? \"play\" : \"pause\"]);\n    }\n  }\n\n  function onAnimationFrame(rate) {\n    var bar = Elements.bar;\n    bar && style(bar, \"width\", rate * 100 + \"%\");\n    emit(EVENT_AUTOPLAY_PLAYING, rate);\n  }\n\n  function onMove(index) {\n    var Slide = Components2.Slides.getAt(index);\n    interval.set(Slide && +getAttribute(Slide.slide, INTERVAL_DATA_ATTRIBUTE) || options.interval);\n  }\n\n  return {\n    mount: mount,\n    destroy: interval.cancel,\n    play: play,\n    pause: pause,\n    isPaused: isPaused\n  };\n}\n\nfunction Cover(Splide2, Components2, options) {\n  var _EventInterface8 = EventInterface(Splide2),\n      on = _EventInterface8.on;\n\n  function mount() {\n    if (options.cover) {\n      on(EVENT_LAZYLOAD_LOADED, apply(toggle, true));\n      on([EVENT_MOUNTED, EVENT_UPDATED, EVENT_REFRESH], apply(cover, true));\n    }\n  }\n\n  function cover(cover2) {\n    Components2.Slides.forEach(function (Slide) {\n      var img = child(Slide.container || Slide.slide, \"img\");\n\n      if (img && img.src) {\n        toggle(cover2, img, Slide);\n      }\n    });\n  }\n\n  function toggle(cover2, img, Slide) {\n    Slide.style(\"background\", cover2 ? \"center/cover no-repeat url(\\\"\" + img.src + \"\\\")\" : \"\", true);\n    display(img, cover2 ? \"none\" : \"\");\n  }\n\n  return {\n    mount: mount,\n    destroy: apply(cover, false)\n  };\n}\n\nvar BOUNCE_DIFF_THRESHOLD = 10;\nvar BOUNCE_DURATION = 600;\nvar FRICTION_FACTOR = 0.6;\nvar BASE_VELOCITY = 1.5;\nvar MIN_DURATION = 800;\n\nfunction Scroll(Splide2, Components2, options) {\n  var _EventInterface9 = EventInterface(Splide2),\n      on = _EventInterface9.on,\n      emit = _EventInterface9.emit;\n\n  var set = Splide2.state.set;\n  var Move = Components2.Move;\n  var getPosition = Move.getPosition,\n      getLimit = Move.getLimit,\n      exceededLimit = Move.exceededLimit,\n      translate = Move.translate;\n  var interval;\n  var callback;\n  var friction = 1;\n\n  function mount() {\n    on(EVENT_MOVE, clear);\n    on([EVENT_UPDATED, EVENT_REFRESH], cancel);\n  }\n\n  function scroll(destination, duration, snap, onScrolled, noConstrain) {\n    var from = getPosition();\n    clear();\n\n    if (snap) {\n      var size = Components2.Layout.sliderSize();\n      var offset = sign(destination) * size * floor(abs(destination) / size) || 0;\n      destination = Move.toPosition(Components2.Controller.toDest(destination % size)) + offset;\n    }\n\n    var noDistance = approximatelyEqual(from, destination, 1);\n    friction = 1;\n    duration = noDistance ? 0 : duration || max(abs(destination - from) / BASE_VELOCITY, MIN_DURATION);\n    callback = onScrolled;\n    interval = RequestInterval(duration, onEnd, apply(update, from, destination, noConstrain), 1);\n    set(SCROLLING);\n    emit(EVENT_SCROLL);\n    interval.start();\n  }\n\n  function onEnd() {\n    set(IDLE);\n    callback && callback();\n    emit(EVENT_SCROLLED);\n  }\n\n  function update(from, to, noConstrain, rate) {\n    var position = getPosition();\n    var target = from + (to - from) * easing(rate);\n    var diff = (target - position) * friction;\n    translate(position + diff);\n\n    if (Splide2.is(SLIDE) && !noConstrain && exceededLimit()) {\n      friction *= FRICTION_FACTOR;\n\n      if (abs(diff) < BOUNCE_DIFF_THRESHOLD) {\n        scroll(getLimit(exceededLimit(true)), BOUNCE_DURATION, false, void 0, true);\n      }\n    }\n  }\n\n  function clear() {\n    if (interval) {\n      interval.cancel();\n    }\n  }\n\n  function cancel() {\n    if (interval && !interval.isPaused()) {\n      clear();\n      onEnd();\n    }\n  }\n\n  function easing(t) {\n    var easingFunc = options.easingFunc;\n    return easingFunc ? easingFunc(t) : 1 - Math.pow(1 - t, 4);\n  }\n\n  return {\n    mount: mount,\n    destroy: clear,\n    scroll: scroll,\n    cancel: cancel\n  };\n}\n\nvar SCROLL_LISTENER_OPTIONS = {\n  passive: false,\n  capture: true\n};\n\nfunction Drag(Splide2, Components2, options) {\n  var _EventInterface10 = EventInterface(Splide2),\n      on = _EventInterface10.on,\n      emit = _EventInterface10.emit,\n      bind = _EventInterface10.bind,\n      unbind = _EventInterface10.unbind;\n\n  var state = Splide2.state;\n  var Move = Components2.Move,\n      Scroll = Components2.Scroll,\n      Controller = Components2.Controller,\n      track = Components2.Elements.track,\n      reduce = Components2.Media.reduce;\n  var _Components2$Directio2 = Components2.Direction,\n      resolve = _Components2$Directio2.resolve,\n      orient = _Components2$Directio2.orient;\n  var getPosition = Move.getPosition,\n      exceededLimit = Move.exceededLimit;\n  var basePosition;\n  var baseEvent;\n  var prevBaseEvent;\n  var isFree;\n  var dragging;\n  var exceeded = false;\n  var clickPrevented;\n  var disabled;\n  var target;\n\n  function mount() {\n    bind(track, POINTER_MOVE_EVENTS, noop, SCROLL_LISTENER_OPTIONS);\n    bind(track, POINTER_UP_EVENTS, noop, SCROLL_LISTENER_OPTIONS);\n    bind(track, POINTER_DOWN_EVENTS, onPointerDown, SCROLL_LISTENER_OPTIONS);\n    bind(track, \"click\", onClick, {\n      capture: true\n    });\n    bind(track, \"dragstart\", prevent);\n    on([EVENT_MOUNTED, EVENT_UPDATED], init);\n  }\n\n  function init() {\n    var drag = options.drag;\n    disable(!drag);\n    isFree = drag === \"free\";\n  }\n\n  function onPointerDown(e) {\n    clickPrevented = false;\n\n    if (!disabled) {\n      var isTouch = isTouchEvent(e);\n\n      if (isDraggable(e.target) && (isTouch || !e.button)) {\n        if (!Controller.isBusy()) {\n          target = isTouch ? track : window;\n          dragging = state.is([MOVING, SCROLLING]);\n          prevBaseEvent = null;\n          bind(target, POINTER_MOVE_EVENTS, onPointerMove, SCROLL_LISTENER_OPTIONS);\n          bind(target, POINTER_UP_EVENTS, onPointerUp, SCROLL_LISTENER_OPTIONS);\n          Move.cancel();\n          Scroll.cancel();\n          save(e);\n        } else {\n          prevent(e, true);\n        }\n      }\n    }\n  }\n\n  function onPointerMove(e) {\n    if (!state.is(DRAGGING)) {\n      state.set(DRAGGING);\n      emit(EVENT_DRAG);\n    }\n\n    if (e.cancelable) {\n      if (dragging) {\n        Move.translate(basePosition + constrain(diffCoord(e)));\n        var expired = diffTime(e) > LOG_INTERVAL;\n        var hasExceeded = exceeded !== (exceeded = exceededLimit());\n\n        if (expired || hasExceeded) {\n          save(e);\n        }\n\n        clickPrevented = true;\n        emit(EVENT_DRAGGING);\n        prevent(e);\n      } else if (isSliderDirection(e)) {\n        dragging = shouldStart(e);\n        prevent(e);\n      }\n    }\n  }\n\n  function onPointerUp(e) {\n    if (state.is(DRAGGING)) {\n      state.set(IDLE);\n      emit(EVENT_DRAGGED);\n    }\n\n    if (dragging) {\n      move(e);\n      prevent(e);\n    }\n\n    unbind(target, POINTER_MOVE_EVENTS, onPointerMove);\n    unbind(target, POINTER_UP_EVENTS, onPointerUp);\n    dragging = false;\n  }\n\n  function onClick(e) {\n    if (!disabled && clickPrevented) {\n      prevent(e, true);\n    }\n  }\n\n  function save(e) {\n    prevBaseEvent = baseEvent;\n    baseEvent = e;\n    basePosition = getPosition();\n  }\n\n  function move(e) {\n    var velocity = computeVelocity(e);\n    var destination = computeDestination(velocity);\n    var rewind = options.rewind && options.rewindByDrag;\n    reduce(false);\n\n    if (isFree) {\n      Controller.scroll(destination, 0, options.snap);\n    } else if (Splide2.is(FADE)) {\n      Controller.go(orient(sign(velocity)) < 0 ? rewind ? \"<\" : \"-\" : rewind ? \">\" : \"+\");\n    } else if (Splide2.is(SLIDE) && exceeded && rewind) {\n      Controller.go(exceededLimit(true) ? \">\" : \"<\");\n    } else {\n      Controller.go(Controller.toDest(destination), true);\n    }\n\n    reduce(true);\n  }\n\n  function shouldStart(e) {\n    var thresholds = options.dragMinThreshold;\n    var isObj = isObject(thresholds);\n    var mouse = isObj && thresholds.mouse || 0;\n    var touch = (isObj ? thresholds.touch : +thresholds) || 10;\n    return abs(diffCoord(e)) > (isTouchEvent(e) ? touch : mouse);\n  }\n\n  function isSliderDirection(e) {\n    return abs(diffCoord(e)) > abs(diffCoord(e, true));\n  }\n\n  function computeVelocity(e) {\n    if (Splide2.is(LOOP) || !exceeded) {\n      var time = diffTime(e);\n\n      if (time && time < LOG_INTERVAL) {\n        return diffCoord(e) / time;\n      }\n    }\n\n    return 0;\n  }\n\n  function computeDestination(velocity) {\n    return getPosition() + sign(velocity) * min(abs(velocity) * (options.flickPower || 600), isFree ? Infinity : Components2.Layout.listSize() * (options.flickMaxPages || 1));\n  }\n\n  function diffCoord(e, orthogonal) {\n    return coordOf(e, orthogonal) - coordOf(getBaseEvent(e), orthogonal);\n  }\n\n  function diffTime(e) {\n    return timeOf(e) - timeOf(getBaseEvent(e));\n  }\n\n  function getBaseEvent(e) {\n    return baseEvent === e && prevBaseEvent || baseEvent;\n  }\n\n  function coordOf(e, orthogonal) {\n    return (isTouchEvent(e) ? e.changedTouches[0] : e)[\"page\" + resolve(orthogonal ? \"Y\" : \"X\")];\n  }\n\n  function constrain(diff) {\n    return diff / (exceeded && Splide2.is(SLIDE) ? FRICTION : 1);\n  }\n\n  function isDraggable(target2) {\n    var noDrag = options.noDrag;\n    return !matches(target2, \".\" + CLASS_PAGINATION_PAGE + \", .\" + CLASS_ARROW) && (!noDrag || !matches(target2, noDrag));\n  }\n\n  function isTouchEvent(e) {\n    return typeof TouchEvent !== \"undefined\" && e instanceof TouchEvent;\n  }\n\n  function isDragging() {\n    return dragging;\n  }\n\n  function disable(value) {\n    disabled = value;\n  }\n\n  return {\n    mount: mount,\n    disable: disable,\n    isDragging: isDragging\n  };\n}\n\nvar NORMALIZATION_MAP = {\n  Spacebar: \" \",\n  Right: ARROW_RIGHT,\n  Left: ARROW_LEFT,\n  Up: ARROW_UP,\n  Down: ARROW_DOWN\n};\n\nfunction normalizeKey(key) {\n  key = isString(key) ? key : key.key;\n  return NORMALIZATION_MAP[key] || key;\n}\n\nvar KEYBOARD_EVENT = \"keydown\";\n\nfunction Keyboard(Splide2, Components2, options) {\n  var _EventInterface11 = EventInterface(Splide2),\n      on = _EventInterface11.on,\n      bind = _EventInterface11.bind,\n      unbind = _EventInterface11.unbind;\n\n  var root = Splide2.root;\n  var resolve = Components2.Direction.resolve;\n  var target;\n  var disabled;\n\n  function mount() {\n    init();\n    on(EVENT_UPDATED, destroy);\n    on(EVENT_UPDATED, init);\n    on(EVENT_MOVE, onMove);\n  }\n\n  function init() {\n    var keyboard = options.keyboard;\n\n    if (keyboard) {\n      target = keyboard === \"global\" ? window : root;\n      bind(target, KEYBOARD_EVENT, onKeydown);\n    }\n  }\n\n  function destroy() {\n    unbind(target, KEYBOARD_EVENT);\n  }\n\n  function disable(value) {\n    disabled = value;\n  }\n\n  function onMove() {\n    var _disabled = disabled;\n    disabled = true;\n    nextTick(function () {\n      disabled = _disabled;\n    });\n  }\n\n  function onKeydown(e) {\n    if (!disabled) {\n      var key = normalizeKey(e);\n\n      if (key === resolve(ARROW_LEFT)) {\n        Splide2.go(\"<\");\n      } else if (key === resolve(ARROW_RIGHT)) {\n        Splide2.go(\">\");\n      }\n    }\n  }\n\n  return {\n    mount: mount,\n    destroy: destroy,\n    disable: disable\n  };\n}\n\nvar SRC_DATA_ATTRIBUTE = DATA_ATTRIBUTE + \"-lazy\";\nvar SRCSET_DATA_ATTRIBUTE = SRC_DATA_ATTRIBUTE + \"-srcset\";\nvar IMAGE_SELECTOR = \"[\" + SRC_DATA_ATTRIBUTE + \"], [\" + SRCSET_DATA_ATTRIBUTE + \"]\";\n\nfunction LazyLoad(Splide2, Components2, options) {\n  var _EventInterface12 = EventInterface(Splide2),\n      on = _EventInterface12.on,\n      off = _EventInterface12.off,\n      bind = _EventInterface12.bind,\n      emit = _EventInterface12.emit;\n\n  var isSequential = options.lazyLoad === \"sequential\";\n  var events = [EVENT_MOUNTED, EVENT_REFRESH, EVENT_MOVED, EVENT_SCROLLED];\n  var entries = [];\n\n  function mount() {\n    if (options.lazyLoad) {\n      init();\n      on(EVENT_REFRESH, init);\n      isSequential || on(events, observe);\n    }\n  }\n\n  function init() {\n    empty(entries);\n    Components2.Slides.forEach(function (Slide) {\n      queryAll(Slide.slide, IMAGE_SELECTOR).forEach(function (img) {\n        var src = getAttribute(img, SRC_DATA_ATTRIBUTE);\n        var srcset = getAttribute(img, SRCSET_DATA_ATTRIBUTE);\n\n        if (src !== img.src || srcset !== img.srcset) {\n          var className = options.classes.spinner;\n          var parent = img.parentElement;\n          var spinner = child(parent, \".\" + className) || create(\"span\", className, parent);\n          entries.push([img, Slide, spinner]);\n          img.src || display(img, \"none\");\n        }\n      });\n    });\n    isSequential && loadNext();\n  }\n\n  function observe() {\n    entries = entries.filter(function (data) {\n      var distance = options.perPage * ((options.preloadPages || 1) + 1) - 1;\n      return data[1].isWithin(Splide2.index, distance) ? load(data) : true;\n    });\n    entries.length || off(events);\n  }\n\n  function load(data) {\n    var img = data[0];\n    addClass(data[1].slide, CLASS_LOADING);\n    bind(img, \"load error\", apply(onLoad, data));\n    setAttribute(img, \"src\", getAttribute(img, SRC_DATA_ATTRIBUTE));\n    setAttribute(img, \"srcset\", getAttribute(img, SRCSET_DATA_ATTRIBUTE));\n    removeAttribute(img, SRC_DATA_ATTRIBUTE);\n    removeAttribute(img, SRCSET_DATA_ATTRIBUTE);\n  }\n\n  function onLoad(data, e) {\n    var img = data[0],\n        Slide = data[1];\n    removeClass(Slide.slide, CLASS_LOADING);\n\n    if (e.type !== \"error\") {\n      remove(data[2]);\n      display(img, \"\");\n      emit(EVENT_LAZYLOAD_LOADED, img, Slide);\n      emit(EVENT_RESIZE);\n    }\n\n    isSequential && loadNext();\n  }\n\n  function loadNext() {\n    entries.length && load(entries.shift());\n  }\n\n  return {\n    mount: mount,\n    destroy: apply(empty, entries)\n  };\n}\n\nfunction Pagination(Splide2, Components2, options) {\n  var event = EventInterface(Splide2);\n  var on = event.on,\n      emit = event.emit,\n      bind = event.bind;\n  var Slides = Components2.Slides,\n      Elements = Components2.Elements,\n      Controller = Components2.Controller;\n  var hasFocus = Controller.hasFocus,\n      getIndex = Controller.getIndex,\n      go = Controller.go;\n  var resolve = Components2.Direction.resolve;\n  var items = [];\n  var list;\n  var paginationClasses;\n\n  function mount() {\n    destroy();\n    on([EVENT_UPDATED, EVENT_REFRESH], mount);\n\n    if (options.pagination && Slides.isEnough()) {\n      on([EVENT_MOVE, EVENT_SCROLL, EVENT_SCROLLED], update);\n      createPagination();\n      update();\n      emit(EVENT_PAGINATION_MOUNTED, {\n        list: list,\n        items: items\n      }, getAt(Splide2.index));\n    }\n  }\n\n  function destroy() {\n    if (list) {\n      remove(Elements.pagination ? slice(list.children) : list);\n      removeClass(list, paginationClasses);\n      empty(items);\n      list = null;\n    }\n\n    event.destroy();\n  }\n\n  function createPagination() {\n    var length = Splide2.length;\n    var classes = options.classes,\n        i18n = options.i18n,\n        perPage = options.perPage;\n    var max = hasFocus() ? length : ceil(length / perPage);\n    list = Elements.pagination || create(\"ul\", classes.pagination, Elements.track.parentElement);\n    addClass(list, paginationClasses = CLASS_PAGINATION + \"--\" + getDirection());\n    setAttribute(list, ROLE, \"tablist\");\n    setAttribute(list, ARIA_LABEL, i18n.select);\n    setAttribute(list, ARIA_ORIENTATION, getDirection() === TTB ? \"vertical\" : \"\");\n\n    for (var i = 0; i < max; i++) {\n      var li = create(\"li\", null, list);\n      var button = create(\"button\", {\n        class: classes.page,\n        type: \"button\"\n      }, li);\n      var controls = Slides.getIn(i).map(function (Slide) {\n        return Slide.slide.id;\n      });\n      var text = !hasFocus() && perPage > 1 ? i18n.pageX : i18n.slideX;\n      bind(button, \"click\", apply(onClick, i));\n\n      if (options.paginationKeyboard) {\n        bind(button, \"keydown\", apply(onKeydown, i));\n      }\n\n      setAttribute(li, ROLE, \"presentation\");\n      setAttribute(button, ROLE, \"tab\");\n      setAttribute(button, ARIA_CONTROLS, controls.join(\" \"));\n      setAttribute(button, ARIA_LABEL, format(text, i + 1));\n      setAttribute(button, TAB_INDEX, -1);\n      items.push({\n        li: li,\n        button: button,\n        page: i\n      });\n    }\n  }\n\n  function onClick(page) {\n    go(\">\" + page, true);\n  }\n\n  function onKeydown(page, e) {\n    var length = items.length;\n    var key = normalizeKey(e);\n    var dir = getDirection();\n    var nextPage = -1;\n\n    if (key === resolve(ARROW_RIGHT, false, dir)) {\n      nextPage = ++page % length;\n    } else if (key === resolve(ARROW_LEFT, false, dir)) {\n      nextPage = (--page + length) % length;\n    } else if (key === \"Home\") {\n      nextPage = 0;\n    } else if (key === \"End\") {\n      nextPage = length - 1;\n    }\n\n    var item = items[nextPage];\n\n    if (item) {\n      focus(item.button);\n      go(\">\" + nextPage);\n      prevent(e, true);\n    }\n  }\n\n  function getDirection() {\n    return options.paginationDirection || options.direction;\n  }\n\n  function getAt(index) {\n    return items[Controller.toPage(index)];\n  }\n\n  function update() {\n    var prev = getAt(getIndex(true));\n    var curr = getAt(getIndex());\n\n    if (prev) {\n      var button = prev.button;\n      removeClass(button, CLASS_ACTIVE);\n      removeAttribute(button, ARIA_SELECTED);\n      setAttribute(button, TAB_INDEX, -1);\n    }\n\n    if (curr) {\n      var _button = curr.button;\n      addClass(_button, CLASS_ACTIVE);\n      setAttribute(_button, ARIA_SELECTED, true);\n      setAttribute(_button, TAB_INDEX, \"\");\n    }\n\n    emit(EVENT_PAGINATION_UPDATED, {\n      list: list,\n      items: items\n    }, prev, curr);\n  }\n\n  return {\n    items: items,\n    mount: mount,\n    destroy: destroy,\n    getAt: getAt,\n    update: update\n  };\n}\n\nvar TRIGGER_KEYS = [\" \", \"Enter\"];\n\nfunction Sync(Splide2, Components2, options) {\n  var isNavigation = options.isNavigation,\n      slideFocus = options.slideFocus;\n  var events = [];\n\n  function setup() {\n    Splide2.options = {\n      slideFocus: isUndefined(slideFocus) ? isNavigation : slideFocus\n    };\n  }\n\n  function mount() {\n    Splide2.splides.forEach(function (target) {\n      if (!target.isParent) {\n        sync(Splide2, target.splide);\n        sync(target.splide, Splide2);\n      }\n    });\n\n    if (isNavigation) {\n      navigate();\n    }\n  }\n\n  function destroy() {\n    events.forEach(function (event) {\n      event.destroy();\n    });\n    empty(events);\n  }\n\n  function remount() {\n    destroy();\n    mount();\n  }\n\n  function sync(splide, target) {\n    var event = EventInterface(splide);\n    event.on(EVENT_MOVE, function (index, prev, dest) {\n      target.go(target.is(LOOP) ? dest : index);\n    });\n    events.push(event);\n  }\n\n  function navigate() {\n    var event = EventInterface(Splide2);\n    var on = event.on;\n    on(EVENT_CLICK, onClick);\n    on(EVENT_SLIDE_KEYDOWN, onKeydown);\n    on([EVENT_MOUNTED, EVENT_UPDATED], update);\n    events.push(event);\n    event.emit(EVENT_NAVIGATION_MOUNTED, Splide2.splides);\n  }\n\n  function update() {\n    setAttribute(Components2.Elements.list, ARIA_ORIENTATION, options.direction === TTB ? \"vertical\" : \"\");\n  }\n\n  function onClick(Slide) {\n    Splide2.go(Slide.index);\n  }\n\n  function onKeydown(Slide, e) {\n    if (includes(TRIGGER_KEYS, normalizeKey(e))) {\n      onClick(Slide);\n      prevent(e);\n    }\n  }\n\n  return {\n    setup: setup,\n    mount: mount,\n    destroy: destroy,\n    remount: remount\n  };\n}\n\nfunction Wheel(Splide2, Components2, options) {\n  var _EventInterface13 = EventInterface(Splide2),\n      bind = _EventInterface13.bind;\n\n  var lastTime = 0;\n\n  function mount() {\n    if (options.wheel) {\n      bind(Components2.Elements.track, \"wheel\", onWheel, SCROLL_LISTENER_OPTIONS);\n    }\n  }\n\n  function onWheel(e) {\n    if (e.cancelable) {\n      var deltaY = e.deltaY;\n      var backwards = deltaY < 0;\n      var timeStamp = timeOf(e);\n\n      var _min = options.wheelMinThreshold || 0;\n\n      var sleep = options.wheelSleep || 0;\n\n      if (abs(deltaY) > _min && timeStamp - lastTime > sleep) {\n        Splide2.go(backwards ? \"<\" : \">\");\n        lastTime = timeStamp;\n      }\n\n      shouldPrevent(backwards) && prevent(e);\n    }\n  }\n\n  function shouldPrevent(backwards) {\n    return !options.releaseWheel || Splide2.state.is(MOVING) || Components2.Controller.getAdjacent(backwards) !== -1;\n  }\n\n  return {\n    mount: mount\n  };\n}\n\nfunction Live(Splide2, Components2, options) {\n  var _EventInterface14 = EventInterface(Splide2),\n      on = _EventInterface14.on;\n\n  var track = Components2.Elements.track;\n  var live = options.live;\n  var enabled = live && !options.isNavigation;\n  var sr = create(\"span\", CLASS_SR);\n\n  function mount() {\n    if (enabled) {\n      disable(!Components2.Autoplay.isPaused());\n      setAttribute(track, ARIA_RELEVANT, \"additions\");\n      sr.textContent = \"\\u2026\";\n      on(EVENT_AUTOPLAY_PLAY, apply(disable, true));\n      on(EVENT_AUTOPLAY_PAUSE, apply(disable, false));\n      on([EVENT_MOVED, EVENT_SCROLLED], apply(append, track, sr));\n    }\n  }\n\n  function destroy() {\n    removeAttribute(track, [ARIA_LIVE, ARIA_RELEVANT]);\n    remove(sr);\n  }\n\n  function disable(disabled) {\n    if (enabled) {\n      setAttribute(track, ARIA_LIVE, disabled ? \"off\" : \"polite\");\n    }\n  }\n\n  return {\n    mount: mount,\n    disable: disable,\n    destroy: destroy\n  };\n}\n\nvar ComponentConstructors = /*#__PURE__*/Object.freeze({\n  __proto__: null,\n  Media: Media,\n  Direction: Direction,\n  Elements: Elements,\n  Slides: Slides,\n  Layout: Layout,\n  Clones: Clones,\n  Move: Move,\n  Controller: Controller,\n  Arrows: Arrows,\n  Autoplay: Autoplay,\n  Cover: Cover,\n  Scroll: Scroll,\n  Drag: Drag,\n  Keyboard: Keyboard,\n  LazyLoad: LazyLoad,\n  Pagination: Pagination,\n  Sync: Sync,\n  Wheel: Wheel,\n  Live: Live\n});\nvar I18N = {\n  prev: \"Previous slide\",\n  next: \"Next slide\",\n  first: \"Go to first slide\",\n  last: \"Go to last slide\",\n  slideX: \"Go to slide %s\",\n  pageX: \"Go to page %s\",\n  play: \"Start autoplay\",\n  pause: \"Pause autoplay\",\n  carousel: \"carousel\",\n  slide: \"slide\",\n  select: \"Select a slide to show\",\n  slideLabel: \"%s of %s\"\n};\nvar DEFAULTS = {\n  type: \"slide\",\n  role: \"region\",\n  speed: 400,\n  perPage: 1,\n  cloneStatus: true,\n  arrows: true,\n  pagination: true,\n  paginationKeyboard: true,\n  interval: 5e3,\n  pauseOnHover: true,\n  pauseOnFocus: true,\n  resetProgress: true,\n  easing: \"cubic-bezier(0.25, 1, 0.5, 1)\",\n  drag: true,\n  direction: \"ltr\",\n  trimSpace: true,\n  focusableNodes: \"a, button, textarea, input, select, iframe\",\n  live: true,\n  classes: CLASSES,\n  i18n: I18N,\n  reducedMotion: {\n    speed: 0,\n    rewindSpeed: 0,\n    autoplay: \"pause\"\n  }\n};\n\nfunction Fade(Splide2, Components2, options) {\n  var _EventInterface15 = EventInterface(Splide2),\n      on = _EventInterface15.on;\n\n  function mount() {\n    on([EVENT_MOUNTED, EVENT_REFRESH], function () {\n      nextTick(function () {\n        Components2.Slides.style(\"transition\", \"opacity \" + options.speed + \"ms \" + options.easing);\n      });\n    });\n  }\n\n  function start(index, done) {\n    var track = Components2.Elements.track;\n    style(track, \"height\", unit(rect(track).height));\n    nextTick(function () {\n      done();\n      style(track, \"height\", \"\");\n    });\n  }\n\n  return {\n    mount: mount,\n    start: start,\n    cancel: noop\n  };\n}\n\nfunction Slide(Splide2, Components2, options) {\n  var _EventInterface16 = EventInterface(Splide2),\n      bind = _EventInterface16.bind;\n\n  var Move = Components2.Move,\n      Controller = Components2.Controller,\n      Scroll = Components2.Scroll;\n  var list = Components2.Elements.list;\n  var transition = apply(style, list, \"transition\");\n  var endCallback;\n\n  function mount() {\n    bind(list, \"transitionend\", function (e) {\n      if (e.target === list && endCallback) {\n        cancel();\n        endCallback();\n      }\n    });\n  }\n\n  function start(index, done) {\n    var destination = Move.toPosition(index, true);\n    var position = Move.getPosition();\n    var speed = getSpeed(index);\n\n    if (abs(destination - position) >= 1 && speed >= 1) {\n      if (options.useScroll) {\n        Scroll.scroll(destination, speed, false, done);\n      } else {\n        transition(\"transform \" + speed + \"ms \" + options.easing);\n        Move.translate(destination, true);\n        endCallback = done;\n      }\n    } else {\n      Move.jump(index);\n      done();\n    }\n  }\n\n  function cancel() {\n    transition(\"\");\n    Scroll.cancel();\n  }\n\n  function getSpeed(index) {\n    var rewindSpeed = options.rewindSpeed;\n\n    if (Splide2.is(SLIDE) && rewindSpeed) {\n      var prev = Controller.getIndex(true);\n      var end = Controller.getEnd();\n\n      if (prev === 0 && index >= end || prev >= end && index === 0) {\n        return rewindSpeed;\n      }\n    }\n\n    return options.speed;\n  }\n\n  return {\n    mount: mount,\n    start: start,\n    cancel: cancel\n  };\n}\n\nvar _Splide = /*#__PURE__*/function () {\n  function _Splide(target, options) {\n    this.event = EventInterface();\n    this.Components = {};\n    this.state = State(CREATED);\n    this.splides = [];\n    this._o = {};\n    this._E = {};\n    var root = isString(target) ? query(document, target) : target;\n    assert(root, root + \" is invalid.\");\n    this.root = root;\n    options = merge({\n      label: getAttribute(root, ARIA_LABEL) || \"\",\n      labelledby: getAttribute(root, ARIA_LABELLEDBY) || \"\"\n    }, DEFAULTS, _Splide.defaults, options || {});\n\n    try {\n      merge(options, JSON.parse(getAttribute(root, DATA_ATTRIBUTE)));\n    } catch (e) {\n      assert(false, \"Invalid JSON\");\n    }\n\n    this._o = Object.create(merge({}, options));\n  }\n\n  var _proto = _Splide.prototype;\n\n  _proto.mount = function mount(Extensions, Transition) {\n    var _this = this;\n\n    var state = this.state,\n        Components2 = this.Components;\n    assert(state.is([CREATED, DESTROYED]), \"Already mounted!\");\n    state.set(CREATED);\n    this._C = Components2;\n    this._T = Transition || this._T || (this.is(FADE) ? Fade : Slide);\n    this._E = Extensions || this._E;\n    var Constructors = assign({}, ComponentConstructors, this._E, {\n      Transition: this._T\n    });\n    forOwn(Constructors, function (Component, key) {\n      var component = Component(_this, Components2, _this._o);\n      Components2[key] = component;\n      component.setup && component.setup();\n    });\n    forOwn(Components2, function (component) {\n      component.mount && component.mount();\n    });\n    this.emit(EVENT_MOUNTED);\n    addClass(this.root, CLASS_INITIALIZED);\n    state.set(IDLE);\n    this.emit(EVENT_READY);\n    return this;\n  };\n\n  _proto.sync = function sync(splide) {\n    this.splides.push({\n      splide: splide\n    });\n    splide.splides.push({\n      splide: this,\n      isParent: true\n    });\n\n    if (this.state.is(IDLE)) {\n      this._C.Sync.remount();\n\n      splide.Components.Sync.remount();\n    }\n\n    return this;\n  };\n\n  _proto.go = function go(control) {\n    this._C.Controller.go(control);\n\n    return this;\n  };\n\n  _proto.on = function on(events, callback) {\n    this.event.on(events, callback);\n    return this;\n  };\n\n  _proto.off = function off(events) {\n    this.event.off(events);\n    return this;\n  };\n\n  _proto.emit = function emit(event) {\n    var _this$event;\n\n    (_this$event = this.event).emit.apply(_this$event, [event].concat(slice(arguments, 1)));\n\n    return this;\n  };\n\n  _proto.add = function add(slides, index) {\n    this._C.Slides.add(slides, index);\n\n    return this;\n  };\n\n  _proto.remove = function remove(matcher) {\n    this._C.Slides.remove(matcher);\n\n    return this;\n  };\n\n  _proto.is = function is(type) {\n    return this._o.type === type;\n  };\n\n  _proto.refresh = function refresh() {\n    this.emit(EVENT_REFRESH);\n    return this;\n  };\n\n  _proto.destroy = function destroy(completely) {\n    if (completely === void 0) {\n      completely = true;\n    }\n\n    var event = this.event,\n        state = this.state;\n\n    if (state.is(CREATED)) {\n      EventInterface(this).on(EVENT_READY, this.destroy.bind(this, completely));\n    } else {\n      forOwn(this._C, function (component) {\n        component.destroy && component.destroy(completely);\n      }, true);\n      event.emit(EVENT_DESTROY);\n      event.destroy();\n      completely && empty(this.splides);\n      state.set(DESTROYED);\n    }\n\n    return this;\n  };\n\n  _createClass(_Splide, [{\n    key: \"options\",\n    get: function get() {\n      return this._o;\n    },\n    set: function set(options) {\n      this._C.Media.set(options, true);\n    }\n  }, {\n    key: \"length\",\n    get: function get() {\n      return this._C.Slides.getLength(true);\n    }\n  }, {\n    key: \"index\",\n    get: function get() {\n      return this._C.Controller.getIndex();\n    }\n  }]);\n\n  return _Splide;\n}();\n\nvar Splide = _Splide;\nSplide.defaults = {};\nSplide.STATES = STATES;\nvar CLASS_RENDERED = \"is-rendered\";\nvar RENDERER_DEFAULT_CONFIG = {\n  listTag: \"ul\",\n  slideTag: \"li\"\n};\n\nvar Style = /*#__PURE__*/function () {\n  function Style(id, options) {\n    this.styles = {};\n    this.id = id;\n    this.options = options;\n  }\n\n  var _proto2 = Style.prototype;\n\n  _proto2.rule = function rule(selector, prop, value, breakpoint) {\n    breakpoint = breakpoint || \"default\";\n    var selectors = this.styles[breakpoint] = this.styles[breakpoint] || {};\n    var styles = selectors[selector] = selectors[selector] || {};\n    styles[prop] = value;\n  };\n\n  _proto2.build = function build() {\n    var _this2 = this;\n\n    var css = \"\";\n\n    if (this.styles.default) {\n      css += this.buildSelectors(this.styles.default);\n    }\n\n    Object.keys(this.styles).sort(function (n, m) {\n      return _this2.options.mediaQuery === \"min\" ? +n - +m : +m - +n;\n    }).forEach(function (breakpoint) {\n      if (breakpoint !== \"default\") {\n        css += \"@media screen and (max-width: \" + breakpoint + \"px) {\";\n        css += _this2.buildSelectors(_this2.styles[breakpoint]);\n        css += \"}\";\n      }\n    });\n    return css;\n  };\n\n  _proto2.buildSelectors = function buildSelectors(selectors) {\n    var _this3 = this;\n\n    var css = \"\";\n    forOwn(selectors, function (styles, selector) {\n      selector = (\"#\" + _this3.id + \" \" + selector).trim();\n      css += selector + \" {\";\n      forOwn(styles, function (value, prop) {\n        if (value || value === 0) {\n          css += prop + \": \" + value + \";\";\n        }\n      });\n      css += \"}\";\n    });\n    return css;\n  };\n\n  return Style;\n}();\n\nvar SplideRenderer = /*#__PURE__*/function () {\n  function SplideRenderer(contents, options, config, defaults) {\n    this.slides = [];\n    this.options = {};\n    this.breakpoints = [];\n    merge(DEFAULTS, defaults || {});\n    merge(merge(this.options, DEFAULTS), options || {});\n    this.contents = contents;\n    this.config = assign({}, RENDERER_DEFAULT_CONFIG, config || {});\n    this.id = this.config.id || uniqueId(\"splide\");\n    this.Style = new Style(this.id, this.options);\n    this.Direction = Direction(null, null, this.options);\n    assert(this.contents.length, \"Provide at least 1 content.\");\n    this.init();\n  }\n\n  SplideRenderer.clean = function clean(splide) {\n    var _EventInterface17 = EventInterface(splide),\n        on = _EventInterface17.on;\n\n    var root = splide.root;\n    var clones = queryAll(root, \".\" + CLASS_CLONE);\n    on(EVENT_MOUNTED, function () {\n      remove(child(root, \"style\"));\n    });\n    remove(clones);\n  };\n\n  var _proto3 = SplideRenderer.prototype;\n\n  _proto3.init = function init() {\n    this.parseBreakpoints();\n    this.initSlides();\n    this.registerRootStyles();\n    this.registerTrackStyles();\n    this.registerSlideStyles();\n    this.registerListStyles();\n  };\n\n  _proto3.initSlides = function initSlides() {\n    var _this4 = this;\n\n    push(this.slides, this.contents.map(function (content, index) {\n      content = isString(content) ? {\n        html: content\n      } : content;\n      content.styles = content.styles || {};\n      content.attrs = content.attrs || {};\n\n      _this4.cover(content);\n\n      var classes = _this4.options.classes.slide + \" \" + (index === 0 ? CLASS_ACTIVE : \"\");\n      assign(content.attrs, {\n        class: (classes + \" \" + (content.attrs.class || \"\")).trim(),\n        style: _this4.buildStyles(content.styles)\n      });\n      return content;\n    }));\n\n    if (this.isLoop()) {\n      this.generateClones(this.slides);\n    }\n  };\n\n  _proto3.registerRootStyles = function registerRootStyles() {\n    var _this5 = this;\n\n    this.breakpoints.forEach(function (_ref2) {\n      var width = _ref2[0],\n          options = _ref2[1];\n\n      _this5.Style.rule(\" \", \"max-width\", unit(options.width), width);\n    });\n  };\n\n  _proto3.registerTrackStyles = function registerTrackStyles() {\n    var _this6 = this;\n\n    var Style2 = this.Style;\n    var selector = \".\" + CLASS_TRACK;\n    this.breakpoints.forEach(function (_ref3) {\n      var width = _ref3[0],\n          options = _ref3[1];\n      Style2.rule(selector, _this6.resolve(\"paddingLeft\"), _this6.cssPadding(options, false), width);\n      Style2.rule(selector, _this6.resolve(\"paddingRight\"), _this6.cssPadding(options, true), width);\n      Style2.rule(selector, \"height\", _this6.cssTrackHeight(options), width);\n    });\n  };\n\n  _proto3.registerListStyles = function registerListStyles() {\n    var _this7 = this;\n\n    var Style2 = this.Style;\n    var selector = \".\" + CLASS_LIST;\n    this.breakpoints.forEach(function (_ref4) {\n      var width = _ref4[0],\n          options = _ref4[1];\n      Style2.rule(selector, \"transform\", _this7.buildTranslate(options), width);\n\n      if (!_this7.cssSlideHeight(options)) {\n        Style2.rule(selector, \"aspect-ratio\", _this7.cssAspectRatio(options), width);\n      }\n    });\n  };\n\n  _proto3.registerSlideStyles = function registerSlideStyles() {\n    var _this8 = this;\n\n    var Style2 = this.Style;\n    var selector = \".\" + CLASS_SLIDE;\n    this.breakpoints.forEach(function (_ref5) {\n      var width = _ref5[0],\n          options = _ref5[1];\n      Style2.rule(selector, \"width\", _this8.cssSlideWidth(options), width);\n      Style2.rule(selector, \"height\", _this8.cssSlideHeight(options) || \"100%\", width);\n      Style2.rule(selector, _this8.resolve(\"marginRight\"), unit(options.gap) || \"0px\", width);\n      Style2.rule(selector + \" > img\", \"display\", options.cover ? \"none\" : \"inline\", width);\n    });\n  };\n\n  _proto3.buildTranslate = function buildTranslate(options) {\n    var _this$Direction = this.Direction,\n        resolve = _this$Direction.resolve,\n        orient = _this$Direction.orient;\n    var values = [];\n    values.push(this.cssOffsetClones(options));\n    values.push(this.cssOffsetGaps(options));\n\n    if (this.isCenter(options)) {\n      values.push(this.buildCssValue(orient(-50), \"%\"));\n      values.push.apply(values, this.cssOffsetCenter(options));\n    }\n\n    return values.filter(Boolean).map(function (value) {\n      return \"translate\" + resolve(\"X\") + \"(\" + value + \")\";\n    }).join(\" \");\n  };\n\n  _proto3.cssOffsetClones = function cssOffsetClones(options) {\n    var _this$Direction2 = this.Direction,\n        resolve = _this$Direction2.resolve,\n        orient = _this$Direction2.orient;\n    var cloneCount = this.getCloneCount();\n\n    if (this.isFixedWidth(options)) {\n      var _this$parseCssValue = this.parseCssValue(options[resolve(\"fixedWidth\")]),\n          value = _this$parseCssValue.value,\n          unit2 = _this$parseCssValue.unit;\n\n      return this.buildCssValue(orient(value) * cloneCount, unit2);\n    }\n\n    var percent = 100 * cloneCount / options.perPage;\n    return orient(percent) + \"%\";\n  };\n\n  _proto3.cssOffsetCenter = function cssOffsetCenter(options) {\n    var _this$Direction3 = this.Direction,\n        resolve = _this$Direction3.resolve,\n        orient = _this$Direction3.orient;\n\n    if (this.isFixedWidth(options)) {\n      var _this$parseCssValue2 = this.parseCssValue(options[resolve(\"fixedWidth\")]),\n          value = _this$parseCssValue2.value,\n          unit2 = _this$parseCssValue2.unit;\n\n      return [this.buildCssValue(orient(value / 2), unit2)];\n    }\n\n    var values = [];\n    var perPage = options.perPage,\n        gap = options.gap;\n    values.push(orient(50 / perPage) + \"%\");\n\n    if (gap) {\n      var _this$parseCssValue3 = this.parseCssValue(gap),\n          _value = _this$parseCssValue3.value,\n          _unit = _this$parseCssValue3.unit;\n\n      var gapOffset = (_value / perPage - _value) / 2;\n      values.push(this.buildCssValue(orient(gapOffset), _unit));\n    }\n\n    return values;\n  };\n\n  _proto3.cssOffsetGaps = function cssOffsetGaps(options) {\n    var cloneCount = this.getCloneCount();\n\n    if (cloneCount && options.gap) {\n      var orient = this.Direction.orient;\n\n      var _this$parseCssValue4 = this.parseCssValue(options.gap),\n          value = _this$parseCssValue4.value,\n          unit2 = _this$parseCssValue4.unit;\n\n      if (this.isFixedWidth(options)) {\n        return this.buildCssValue(orient(value * cloneCount), unit2);\n      }\n\n      var perPage = options.perPage;\n      var gaps = cloneCount / perPage;\n      return this.buildCssValue(orient(gaps * value), unit2);\n    }\n\n    return \"\";\n  };\n\n  _proto3.resolve = function resolve(prop) {\n    return camelToKebab(this.Direction.resolve(prop));\n  };\n\n  _proto3.cssPadding = function cssPadding(options, right) {\n    var padding = options.padding;\n    var prop = this.Direction.resolve(right ? \"right\" : \"left\", true);\n    return padding && unit(padding[prop] || (isObject(padding) ? 0 : padding)) || \"0px\";\n  };\n\n  _proto3.cssTrackHeight = function cssTrackHeight(options) {\n    var height = \"\";\n\n    if (this.isVertical()) {\n      height = this.cssHeight(options);\n      assert(height, '\"height\" is missing.');\n      height = \"calc(\" + height + \" - \" + this.cssPadding(options, false) + \" - \" + this.cssPadding(options, true) + \")\";\n    }\n\n    return height;\n  };\n\n  _proto3.cssHeight = function cssHeight(options) {\n    return unit(options.height);\n  };\n\n  _proto3.cssSlideWidth = function cssSlideWidth(options) {\n    return options.autoWidth ? \"\" : unit(options.fixedWidth) || (this.isVertical() ? \"\" : this.cssSlideSize(options));\n  };\n\n  _proto3.cssSlideHeight = function cssSlideHeight(options) {\n    return unit(options.fixedHeight) || (this.isVertical() ? options.autoHeight ? \"\" : this.cssSlideSize(options) : this.cssHeight(options));\n  };\n\n  _proto3.cssSlideSize = function cssSlideSize(options) {\n    var gap = unit(options.gap);\n    return \"calc((100%\" + (gap && \" + \" + gap) + \")/\" + (options.perPage || 1) + (gap && \" - \" + gap) + \")\";\n  };\n\n  _proto3.cssAspectRatio = function cssAspectRatio(options) {\n    var heightRatio = options.heightRatio;\n    return heightRatio ? \"\" + 1 / heightRatio : \"\";\n  };\n\n  _proto3.buildCssValue = function buildCssValue(value, unit2) {\n    return \"\" + value + unit2;\n  };\n\n  _proto3.parseCssValue = function parseCssValue(value) {\n    if (isString(value)) {\n      var number = parseFloat(value) || 0;\n      var unit2 = value.replace(/\\d*(\\.\\d*)?/, \"\") || \"px\";\n      return {\n        value: number,\n        unit: unit2\n      };\n    }\n\n    return {\n      value: value,\n      unit: \"px\"\n    };\n  };\n\n  _proto3.parseBreakpoints = function parseBreakpoints() {\n    var _this9 = this;\n\n    var breakpoints = this.options.breakpoints;\n    this.breakpoints.push([\"default\", this.options]);\n\n    if (breakpoints) {\n      forOwn(breakpoints, function (options, width) {\n        _this9.breakpoints.push([width, merge(merge({}, _this9.options), options)]);\n      });\n    }\n  };\n\n  _proto3.isFixedWidth = function isFixedWidth(options) {\n    return !!options[this.Direction.resolve(\"fixedWidth\")];\n  };\n\n  _proto3.isLoop = function isLoop() {\n    return this.options.type === LOOP;\n  };\n\n  _proto3.isCenter = function isCenter(options) {\n    if (options.focus === \"center\") {\n      if (this.isLoop()) {\n        return true;\n      }\n\n      if (this.options.type === SLIDE) {\n        return !this.options.trimSpace;\n      }\n    }\n\n    return false;\n  };\n\n  _proto3.isVertical = function isVertical() {\n    return this.options.direction === TTB;\n  };\n\n  _proto3.buildClasses = function buildClasses() {\n    var options = this.options;\n    return [CLASS_ROOT, CLASS_ROOT + \"--\" + options.type, CLASS_ROOT + \"--\" + options.direction, options.drag && CLASS_ROOT + \"--draggable\", options.isNavigation && CLASS_ROOT + \"--nav\", CLASS_ACTIVE, !this.config.hidden && CLASS_RENDERED].filter(Boolean).join(\" \");\n  };\n\n  _proto3.buildAttrs = function buildAttrs(attrs) {\n    var attr = \"\";\n    forOwn(attrs, function (value, key) {\n      attr += value ? \" \" + camelToKebab(key) + \"=\\\"\" + value + \"\\\"\" : \"\";\n    });\n    return attr.trim();\n  };\n\n  _proto3.buildStyles = function buildStyles(styles) {\n    var style = \"\";\n    forOwn(styles, function (value, key) {\n      style += \" \" + camelToKebab(key) + \":\" + value + \";\";\n    });\n    return style.trim();\n  };\n\n  _proto3.renderSlides = function renderSlides() {\n    var _this10 = this;\n\n    var tag = this.config.slideTag;\n    return this.slides.map(function (content) {\n      return \"<\" + tag + \" \" + _this10.buildAttrs(content.attrs) + \">\" + (content.html || \"\") + \"</\" + tag + \">\";\n    }).join(\"\");\n  };\n\n  _proto3.cover = function cover(content) {\n    var styles = content.styles,\n        _content$html = content.html,\n        html = _content$html === void 0 ? \"\" : _content$html;\n\n    if (this.options.cover && !this.options.lazyLoad) {\n      var src = html.match(/<img.*?src\\s*=\\s*(['\"])(.+?)\\1.*?>/);\n\n      if (src && src[2]) {\n        styles.background = \"center/cover no-repeat url('\" + src[2] + \"')\";\n      }\n    }\n  };\n\n  _proto3.generateClones = function generateClones(contents) {\n    var classes = this.options.classes;\n    var count = this.getCloneCount();\n    var slides = contents.slice();\n\n    while (slides.length < count) {\n      push(slides, slides);\n    }\n\n    push(slides.slice(-count).reverse(), slides.slice(0, count)).forEach(function (content, index) {\n      var attrs = assign({}, content.attrs, {\n        class: content.attrs.class + \" \" + classes.clone\n      });\n      var clone = assign({}, content, {\n        attrs: attrs\n      });\n      index < count ? contents.unshift(clone) : contents.push(clone);\n    });\n  };\n\n  _proto3.getCloneCount = function getCloneCount() {\n    if (this.isLoop()) {\n      var options = this.options;\n\n      if (options.clones) {\n        return options.clones;\n      }\n\n      var perPage = max.apply(void 0, this.breakpoints.map(function (_ref6) {\n        var options2 = _ref6[1];\n        return options2.perPage;\n      }));\n      return perPage * ((options.flickMaxPages || 1) + 1);\n    }\n\n    return 0;\n  };\n\n  _proto3.renderArrows = function renderArrows() {\n    var html = \"\";\n    html += \"<div class=\\\"\" + this.options.classes.arrows + \"\\\">\";\n    html += this.renderArrow(true);\n    html += this.renderArrow(false);\n    html += \"</div>\";\n    return html;\n  };\n\n  _proto3.renderArrow = function renderArrow(prev) {\n    var _this$options = this.options,\n        classes = _this$options.classes,\n        i18n = _this$options.i18n;\n    var attrs = {\n      class: classes.arrow + \" \" + (prev ? classes.prev : classes.next),\n      type: \"button\",\n      ariaLabel: prev ? i18n.prev : i18n.next\n    };\n    return \"<button \" + this.buildAttrs(attrs) + \"><svg xmlns=\\\"\" + XML_NAME_SPACE + \"\\\" viewBox=\\\"0 0 \" + SIZE + \" \" + SIZE + \"\\\" width=\\\"\" + SIZE + \"\\\" height=\\\"\" + SIZE + \"\\\"><path d=\\\"\" + (this.options.arrowPath || PATH) + \"\\\" /></svg></button>\";\n  };\n\n  _proto3.html = function html() {\n    var _this$config = this.config,\n        rootClass = _this$config.rootClass,\n        listTag = _this$config.listTag,\n        arrows = _this$config.arrows,\n        beforeTrack = _this$config.beforeTrack,\n        afterTrack = _this$config.afterTrack,\n        slider = _this$config.slider,\n        beforeSlider = _this$config.beforeSlider,\n        afterSlider = _this$config.afterSlider;\n    var html = \"\";\n    html += \"<div id=\\\"\" + this.id + \"\\\" class=\\\"\" + this.buildClasses() + \" \" + (rootClass || \"\") + \"\\\">\";\n    html += \"<style>\" + this.Style.build() + \"</style>\";\n\n    if (slider) {\n      html += beforeSlider || \"\";\n      html += \"<div class=\\\"splide__slider\\\">\";\n    }\n\n    html += beforeTrack || \"\";\n\n    if (arrows) {\n      html += this.renderArrows();\n    }\n\n    html += \"<div class=\\\"splide__track\\\">\";\n    html += \"<\" + listTag + \" class=\\\"splide__list\\\">\";\n    html += this.renderSlides();\n    html += \"</\" + listTag + \">\";\n    html += \"</div>\";\n    html += afterTrack || \"\";\n\n    if (slider) {\n      html += \"</div>\";\n      html += afterSlider || \"\";\n    }\n\n    html += \"</div>\";\n    return html;\n  };\n\n  return SplideRenderer;\n}();\n\nexport { CLASSES, CLASS_ACTIVE, CLASS_ARROW, CLASS_ARROWS, CLASS_ARROW_NEXT, CLASS_ARROW_PREV, CLASS_CLONE, CLASS_CONTAINER, CLASS_FOCUS_IN, CLASS_INITIALIZED, CLASS_LIST, CLASS_LOADING, CLASS_NEXT, CLASS_PAGINATION, CLASS_PAGINATION_PAGE, CLASS_PREV, CLASS_PROGRESS, CLASS_PROGRESS_BAR, CLASS_ROOT, CLASS_SLIDE, CLASS_SPINNER, CLASS_SR, CLASS_TOGGLE, CLASS_TOGGLE_PAUSE, CLASS_TOGGLE_PLAY, CLASS_TRACK, CLASS_VISIBLE, DEFAULTS, EVENT_ACTIVE, EVENT_ARROWS_MOUNTED, EVENT_ARROWS_UPDATED, EVENT_AUTOPLAY_PAUSE, EVENT_AUTOPLAY_PLAY, EVENT_AUTOPLAY_PLAYING, EVENT_CLICK, EVENT_DESTROY, EVENT_DRAG, EVENT_DRAGGED, EVENT_DRAGGING, EVENT_HIDDEN, EVENT_INACTIVE, EVENT_LAZYLOAD_LOADED, EVENT_MOUNTED, EVENT_MOVE, EVENT_MOVED, EVENT_NAVIGATION_MOUNTED, EVENT_PAGINATION_MOUNTED, EVENT_PAGINATION_UPDATED, EVENT_READY, EVENT_REFRESH, EVENT_RESIZE, EVENT_RESIZED, EVENT_SCROLL, EVENT_SCROLLED, EVENT_SHIFTED, EVENT_SLIDE_KEYDOWN, EVENT_UPDATED, EVENT_VISIBLE, EventBinder, EventInterface, FADE, LOOP, LTR, RTL, RequestInterval, SLIDE, STATUS_CLASSES, Splide, SplideRenderer, State, TTB, Throttle, Splide as default };\n", "// packages/alpinejs/src/scheduler.js\nvar flushPending = false;\nvar flushing = false;\nvar queue = [];\nfunction scheduler(callback) {\n  queueJob(callback);\n}\nfunction queueJob(job) {\n  if (!queue.includes(job))\n    queue.push(job);\n  queueFlush();\n}\nfunction dequeueJob(job) {\n  let index = queue.indexOf(job);\n  if (index !== -1)\n    queue.splice(index, 1);\n}\nfunction queueFlush() {\n  if (!flushing && !flushPending) {\n    flushPending = true;\n    queueMicrotask(flushJobs);\n  }\n}\nfunction flushJobs() {\n  flushPending = false;\n  flushing = true;\n  for (let i = 0; i < queue.length; i++) {\n    queue[i]();\n  }\n  queue.length = 0;\n  flushing = false;\n}\n\n// packages/alpinejs/src/reactivity.js\nvar reactive;\nvar effect;\nvar release;\nvar raw;\nvar shouldSchedule = true;\nfunction disableEffectScheduling(callback) {\n  shouldSchedule = false;\n  callback();\n  shouldSchedule = true;\n}\nfunction setReactivityEngine(engine) {\n  reactive = engine.reactive;\n  release = engine.release;\n  effect = (callback) => engine.effect(callback, {scheduler: (task) => {\n    if (shouldSchedule) {\n      scheduler(task);\n    } else {\n      task();\n    }\n  }});\n  raw = engine.raw;\n}\nfunction overrideEffect(override) {\n  effect = override;\n}\nfunction elementBoundEffect(el) {\n  let cleanup2 = () => {\n  };\n  let wrappedEffect = (callback) => {\n    let effectReference = effect(callback);\n    if (!el._x_effects) {\n      el._x_effects = new Set();\n      el._x_runEffects = () => {\n        el._x_effects.forEach((i) => i());\n      };\n    }\n    el._x_effects.add(effectReference);\n    cleanup2 = () => {\n      if (effectReference === void 0)\n        return;\n      el._x_effects.delete(effectReference);\n      release(effectReference);\n    };\n    return effectReference;\n  };\n  return [wrappedEffect, () => {\n    cleanup2();\n  }];\n}\n\n// packages/alpinejs/src/mutation.js\nvar onAttributeAddeds = [];\nvar onElRemoveds = [];\nvar onElAddeds = [];\nfunction onElAdded(callback) {\n  onElAddeds.push(callback);\n}\nfunction onElRemoved(el, callback) {\n  if (typeof callback === \"function\") {\n    if (!el._x_cleanups)\n      el._x_cleanups = [];\n    el._x_cleanups.push(callback);\n  } else {\n    callback = el;\n    onElRemoveds.push(callback);\n  }\n}\nfunction onAttributesAdded(callback) {\n  onAttributeAddeds.push(callback);\n}\nfunction onAttributeRemoved(el, name, callback) {\n  if (!el._x_attributeCleanups)\n    el._x_attributeCleanups = {};\n  if (!el._x_attributeCleanups[name])\n    el._x_attributeCleanups[name] = [];\n  el._x_attributeCleanups[name].push(callback);\n}\nfunction cleanupAttributes(el, names) {\n  if (!el._x_attributeCleanups)\n    return;\n  Object.entries(el._x_attributeCleanups).forEach(([name, value]) => {\n    if (names === void 0 || names.includes(name)) {\n      value.forEach((i) => i());\n      delete el._x_attributeCleanups[name];\n    }\n  });\n}\nvar observer = new MutationObserver(onMutate);\nvar currentlyObserving = false;\nfunction startObservingMutations() {\n  observer.observe(document, {subtree: true, childList: true, attributes: true, attributeOldValue: true});\n  currentlyObserving = true;\n}\nfunction stopObservingMutations() {\n  flushObserver();\n  observer.disconnect();\n  currentlyObserving = false;\n}\nvar recordQueue = [];\nvar willProcessRecordQueue = false;\nfunction flushObserver() {\n  recordQueue = recordQueue.concat(observer.takeRecords());\n  if (recordQueue.length && !willProcessRecordQueue) {\n    willProcessRecordQueue = true;\n    queueMicrotask(() => {\n      processRecordQueue();\n      willProcessRecordQueue = false;\n    });\n  }\n}\nfunction processRecordQueue() {\n  onMutate(recordQueue);\n  recordQueue.length = 0;\n}\nfunction mutateDom(callback) {\n  if (!currentlyObserving)\n    return callback();\n  stopObservingMutations();\n  let result = callback();\n  startObservingMutations();\n  return result;\n}\nvar isCollecting = false;\nvar deferredMutations = [];\nfunction deferMutations() {\n  isCollecting = true;\n}\nfunction flushAndStopDeferringMutations() {\n  isCollecting = false;\n  onMutate(deferredMutations);\n  deferredMutations = [];\n}\nfunction onMutate(mutations) {\n  if (isCollecting) {\n    deferredMutations = deferredMutations.concat(mutations);\n    return;\n  }\n  let addedNodes = [];\n  let removedNodes = [];\n  let addedAttributes = new Map();\n  let removedAttributes = new Map();\n  for (let i = 0; i < mutations.length; i++) {\n    if (mutations[i].target._x_ignoreMutationObserver)\n      continue;\n    if (mutations[i].type === \"childList\") {\n      mutations[i].addedNodes.forEach((node) => node.nodeType === 1 && addedNodes.push(node));\n      mutations[i].removedNodes.forEach((node) => node.nodeType === 1 && removedNodes.push(node));\n    }\n    if (mutations[i].type === \"attributes\") {\n      let el = mutations[i].target;\n      let name = mutations[i].attributeName;\n      let oldValue = mutations[i].oldValue;\n      let add2 = () => {\n        if (!addedAttributes.has(el))\n          addedAttributes.set(el, []);\n        addedAttributes.get(el).push({name, value: el.getAttribute(name)});\n      };\n      let remove = () => {\n        if (!removedAttributes.has(el))\n          removedAttributes.set(el, []);\n        removedAttributes.get(el).push(name);\n      };\n      if (el.hasAttribute(name) && oldValue === null) {\n        add2();\n      } else if (el.hasAttribute(name)) {\n        remove();\n        add2();\n      } else {\n        remove();\n      }\n    }\n  }\n  removedAttributes.forEach((attrs, el) => {\n    cleanupAttributes(el, attrs);\n  });\n  addedAttributes.forEach((attrs, el) => {\n    onAttributeAddeds.forEach((i) => i(el, attrs));\n  });\n  for (let node of removedNodes) {\n    if (addedNodes.includes(node))\n      continue;\n    onElRemoveds.forEach((i) => i(node));\n    if (node._x_cleanups) {\n      while (node._x_cleanups.length)\n        node._x_cleanups.pop()();\n    }\n  }\n  addedNodes.forEach((node) => {\n    node._x_ignoreSelf = true;\n    node._x_ignore = true;\n  });\n  for (let node of addedNodes) {\n    if (removedNodes.includes(node))\n      continue;\n    if (!node.isConnected)\n      continue;\n    delete node._x_ignoreSelf;\n    delete node._x_ignore;\n    onElAddeds.forEach((i) => i(node));\n    node._x_ignore = true;\n    node._x_ignoreSelf = true;\n  }\n  addedNodes.forEach((node) => {\n    delete node._x_ignoreSelf;\n    delete node._x_ignore;\n  });\n  addedNodes = null;\n  removedNodes = null;\n  addedAttributes = null;\n  removedAttributes = null;\n}\n\n// packages/alpinejs/src/scope.js\nfunction scope(node) {\n  return mergeProxies(closestDataStack(node));\n}\nfunction addScopeToNode(node, data2, referenceNode) {\n  node._x_dataStack = [data2, ...closestDataStack(referenceNode || node)];\n  return () => {\n    node._x_dataStack = node._x_dataStack.filter((i) => i !== data2);\n  };\n}\nfunction refreshScope(element, scope2) {\n  let existingScope = element._x_dataStack[0];\n  Object.entries(scope2).forEach(([key, value]) => {\n    existingScope[key] = value;\n  });\n}\nfunction closestDataStack(node) {\n  if (node._x_dataStack)\n    return node._x_dataStack;\n  if (typeof ShadowRoot === \"function\" && node instanceof ShadowRoot) {\n    return closestDataStack(node.host);\n  }\n  if (!node.parentNode) {\n    return [];\n  }\n  return closestDataStack(node.parentNode);\n}\nfunction mergeProxies(objects) {\n  let thisProxy = new Proxy({}, {\n    ownKeys: () => {\n      return Array.from(new Set(objects.flatMap((i) => Object.keys(i))));\n    },\n    has: (target, name) => {\n      return objects.some((obj) => obj.hasOwnProperty(name));\n    },\n    get: (target, name) => {\n      return (objects.find((obj) => {\n        if (obj.hasOwnProperty(name)) {\n          let descriptor = Object.getOwnPropertyDescriptor(obj, name);\n          if (descriptor.get && descriptor.get._x_alreadyBound || descriptor.set && descriptor.set._x_alreadyBound) {\n            return true;\n          }\n          if ((descriptor.get || descriptor.set) && descriptor.enumerable) {\n            let getter = descriptor.get;\n            let setter = descriptor.set;\n            let property = descriptor;\n            getter = getter && getter.bind(thisProxy);\n            setter = setter && setter.bind(thisProxy);\n            if (getter)\n              getter._x_alreadyBound = true;\n            if (setter)\n              setter._x_alreadyBound = true;\n            Object.defineProperty(obj, name, {\n              ...property,\n              get: getter,\n              set: setter\n            });\n          }\n          return true;\n        }\n        return false;\n      }) || {})[name];\n    },\n    set: (target, name, value) => {\n      let closestObjectWithKey = objects.find((obj) => obj.hasOwnProperty(name));\n      if (closestObjectWithKey) {\n        closestObjectWithKey[name] = value;\n      } else {\n        objects[objects.length - 1][name] = value;\n      }\n      return true;\n    }\n  });\n  return thisProxy;\n}\n\n// packages/alpinejs/src/interceptor.js\nfunction initInterceptors(data2) {\n  let isObject2 = (val) => typeof val === \"object\" && !Array.isArray(val) && val !== null;\n  let recurse = (obj, basePath = \"\") => {\n    Object.entries(Object.getOwnPropertyDescriptors(obj)).forEach(([key, {value, enumerable}]) => {\n      if (enumerable === false || value === void 0)\n        return;\n      let path = basePath === \"\" ? key : `${basePath}.${key}`;\n      if (typeof value === \"object\" && value !== null && value._x_interceptor) {\n        obj[key] = value.initialize(data2, path, key);\n      } else {\n        if (isObject2(value) && value !== obj && !(value instanceof Element)) {\n          recurse(value, path);\n        }\n      }\n    });\n  };\n  return recurse(data2);\n}\nfunction interceptor(callback, mutateObj = () => {\n}) {\n  let obj = {\n    initialValue: void 0,\n    _x_interceptor: true,\n    initialize(data2, path, key) {\n      return callback(this.initialValue, () => get(data2, path), (value) => set(data2, path, value), path, key);\n    }\n  };\n  mutateObj(obj);\n  return (initialValue) => {\n    if (typeof initialValue === \"object\" && initialValue !== null && initialValue._x_interceptor) {\n      let initialize = obj.initialize.bind(obj);\n      obj.initialize = (data2, path, key) => {\n        let innerValue = initialValue.initialize(data2, path, key);\n        obj.initialValue = innerValue;\n        return initialize(data2, path, key);\n      };\n    } else {\n      obj.initialValue = initialValue;\n    }\n    return obj;\n  };\n}\nfunction get(obj, path) {\n  return path.split(\".\").reduce((carry, segment) => carry[segment], obj);\n}\nfunction set(obj, path, value) {\n  if (typeof path === \"string\")\n    path = path.split(\".\");\n  if (path.length === 1)\n    obj[path[0]] = value;\n  else if (path.length === 0)\n    throw error;\n  else {\n    if (obj[path[0]])\n      return set(obj[path[0]], path.slice(1), value);\n    else {\n      obj[path[0]] = {};\n      return set(obj[path[0]], path.slice(1), value);\n    }\n  }\n}\n\n// packages/alpinejs/src/magics.js\nvar magics = {};\nfunction magic(name, callback) {\n  magics[name] = callback;\n}\nfunction injectMagics(obj, el) {\n  Object.entries(magics).forEach(([name, callback]) => {\n    Object.defineProperty(obj, `$${name}`, {\n      get() {\n        let [utilities, cleanup2] = getElementBoundUtilities(el);\n        utilities = {interceptor, ...utilities};\n        onElRemoved(el, cleanup2);\n        return callback(el, utilities);\n      },\n      enumerable: false\n    });\n  });\n  return obj;\n}\n\n// packages/alpinejs/src/utils/error.js\nfunction tryCatch(el, expression, callback, ...args) {\n  try {\n    return callback(...args);\n  } catch (e) {\n    handleError(e, el, expression);\n  }\n}\nfunction handleError(error2, el, expression = void 0) {\n  Object.assign(error2, {el, expression});\n  console.warn(`Alpine Expression Error: ${error2.message}\n\n${expression ? 'Expression: \"' + expression + '\"\\n\\n' : \"\"}`, el);\n  setTimeout(() => {\n    throw error2;\n  }, 0);\n}\n\n// packages/alpinejs/src/evaluator.js\nfunction evaluate(el, expression, extras = {}) {\n  let result;\n  evaluateLater(el, expression)((value) => result = value, extras);\n  return result;\n}\nfunction evaluateLater(...args) {\n  return theEvaluatorFunction(...args);\n}\nvar theEvaluatorFunction = normalEvaluator;\nfunction setEvaluator(newEvaluator) {\n  theEvaluatorFunction = newEvaluator;\n}\nfunction normalEvaluator(el, expression) {\n  let overriddenMagics = {};\n  injectMagics(overriddenMagics, el);\n  let dataStack = [overriddenMagics, ...closestDataStack(el)];\n  if (typeof expression === \"function\") {\n    return generateEvaluatorFromFunction(dataStack, expression);\n  }\n  let evaluator = generateEvaluatorFromString(dataStack, expression, el);\n  return tryCatch.bind(null, el, expression, evaluator);\n}\nfunction generateEvaluatorFromFunction(dataStack, func) {\n  return (receiver = () => {\n  }, {scope: scope2 = {}, params = []} = {}) => {\n    let result = func.apply(mergeProxies([scope2, ...dataStack]), params);\n    runIfTypeOfFunction(receiver, result);\n  };\n}\nvar evaluatorMemo = {};\nfunction generateFunctionFromString(expression, el) {\n  if (evaluatorMemo[expression]) {\n    return evaluatorMemo[expression];\n  }\n  let AsyncFunction = Object.getPrototypeOf(async function() {\n  }).constructor;\n  let rightSideSafeExpression = /^[\\n\\s]*if.*\\(.*\\)/.test(expression) || /^(let|const)\\s/.test(expression) ? `(() => { ${expression} })()` : expression;\n  const safeAsyncFunction = () => {\n    try {\n      return new AsyncFunction([\"__self\", \"scope\"], `with (scope) { __self.result = ${rightSideSafeExpression} }; __self.finished = true; return __self.result;`);\n    } catch (error2) {\n      handleError(error2, el, expression);\n      return Promise.resolve();\n    }\n  };\n  let func = safeAsyncFunction();\n  evaluatorMemo[expression] = func;\n  return func;\n}\nfunction generateEvaluatorFromString(dataStack, expression, el) {\n  let func = generateFunctionFromString(expression, el);\n  return (receiver = () => {\n  }, {scope: scope2 = {}, params = []} = {}) => {\n    func.result = void 0;\n    func.finished = false;\n    let completeScope = mergeProxies([scope2, ...dataStack]);\n    if (typeof func === \"function\") {\n      let promise = func(func, completeScope).catch((error2) => handleError(error2, el, expression));\n      if (func.finished) {\n        runIfTypeOfFunction(receiver, func.result, completeScope, params, el);\n        func.result = void 0;\n      } else {\n        promise.then((result) => {\n          runIfTypeOfFunction(receiver, result, completeScope, params, el);\n        }).catch((error2) => handleError(error2, el, expression)).finally(() => func.result = void 0);\n      }\n    }\n  };\n}\nfunction runIfTypeOfFunction(receiver, value, scope2, params, el) {\n  if (typeof value === \"function\") {\n    let result = value.apply(scope2, params);\n    if (result instanceof Promise) {\n      result.then((i) => runIfTypeOfFunction(receiver, i, scope2, params)).catch((error2) => handleError(error2, el, value));\n    } else {\n      receiver(result);\n    }\n  } else {\n    receiver(value);\n  }\n}\n\n// packages/alpinejs/src/directives.js\nvar prefixAsString = \"x-\";\nfunction prefix(subject = \"\") {\n  return prefixAsString + subject;\n}\nfunction setPrefix(newPrefix) {\n  prefixAsString = newPrefix;\n}\nvar directiveHandlers = {};\nfunction directive(name, callback) {\n  directiveHandlers[name] = callback;\n}\nfunction directives(el, attributes, originalAttributeOverride) {\n  let transformedAttributeMap = {};\n  let directives2 = Array.from(attributes).map(toTransformedAttributes((newName, oldName) => transformedAttributeMap[newName] = oldName)).filter(outNonAlpineAttributes).map(toParsedDirectives(transformedAttributeMap, originalAttributeOverride)).sort(byPriority);\n  return directives2.map((directive2) => {\n    return getDirectiveHandler(el, directive2);\n  });\n}\nfunction attributesOnly(attributes) {\n  return Array.from(attributes).map(toTransformedAttributes()).filter((attr) => !outNonAlpineAttributes(attr));\n}\nvar isDeferringHandlers = false;\nvar directiveHandlerStacks = new Map();\nvar currentHandlerStackKey = Symbol();\nfunction deferHandlingDirectives(callback) {\n  isDeferringHandlers = true;\n  let key = Symbol();\n  currentHandlerStackKey = key;\n  directiveHandlerStacks.set(key, []);\n  let flushHandlers = () => {\n    while (directiveHandlerStacks.get(key).length)\n      directiveHandlerStacks.get(key).shift()();\n    directiveHandlerStacks.delete(key);\n  };\n  let stopDeferring = () => {\n    isDeferringHandlers = false;\n    flushHandlers();\n  };\n  callback(flushHandlers);\n  stopDeferring();\n}\nfunction getElementBoundUtilities(el) {\n  let cleanups = [];\n  let cleanup2 = (callback) => cleanups.push(callback);\n  let [effect3, cleanupEffect] = elementBoundEffect(el);\n  cleanups.push(cleanupEffect);\n  let utilities = {\n    Alpine: alpine_default,\n    effect: effect3,\n    cleanup: cleanup2,\n    evaluateLater: evaluateLater.bind(evaluateLater, el),\n    evaluate: evaluate.bind(evaluate, el)\n  };\n  let doCleanup = () => cleanups.forEach((i) => i());\n  return [utilities, doCleanup];\n}\nfunction getDirectiveHandler(el, directive2) {\n  let noop = () => {\n  };\n  let handler3 = directiveHandlers[directive2.type] || noop;\n  let [utilities, cleanup2] = getElementBoundUtilities(el);\n  onAttributeRemoved(el, directive2.original, cleanup2);\n  let fullHandler = () => {\n    if (el._x_ignore || el._x_ignoreSelf)\n      return;\n    handler3.inline && handler3.inline(el, directive2, utilities);\n    handler3 = handler3.bind(handler3, el, directive2, utilities);\n    isDeferringHandlers ? directiveHandlerStacks.get(currentHandlerStackKey).push(handler3) : handler3();\n  };\n  fullHandler.runCleanups = cleanup2;\n  return fullHandler;\n}\nvar startingWith = (subject, replacement) => ({name, value}) => {\n  if (name.startsWith(subject))\n    name = name.replace(subject, replacement);\n  return {name, value};\n};\nvar into = (i) => i;\nfunction toTransformedAttributes(callback = () => {\n}) {\n  return ({name, value}) => {\n    let {name: newName, value: newValue} = attributeTransformers.reduce((carry, transform) => {\n      return transform(carry);\n    }, {name, value});\n    if (newName !== name)\n      callback(newName, name);\n    return {name: newName, value: newValue};\n  };\n}\nvar attributeTransformers = [];\nfunction mapAttributes(callback) {\n  attributeTransformers.push(callback);\n}\nfunction outNonAlpineAttributes({name}) {\n  return alpineAttributeRegex().test(name);\n}\nvar alpineAttributeRegex = () => new RegExp(`^${prefixAsString}([^:^.]+)\\\\b`);\nfunction toParsedDirectives(transformedAttributeMap, originalAttributeOverride) {\n  return ({name, value}) => {\n    let typeMatch = name.match(alpineAttributeRegex());\n    let valueMatch = name.match(/:([a-zA-Z0-9\\-:]+)/);\n    let modifiers = name.match(/\\.[^.\\]]+(?=[^\\]]*$)/g) || [];\n    let original = originalAttributeOverride || transformedAttributeMap[name] || name;\n    return {\n      type: typeMatch ? typeMatch[1] : null,\n      value: valueMatch ? valueMatch[1] : null,\n      modifiers: modifiers.map((i) => i.replace(\".\", \"\")),\n      expression: value,\n      original\n    };\n  };\n}\nvar DEFAULT = \"DEFAULT\";\nvar directiveOrder = [\n  \"ignore\",\n  \"ref\",\n  \"data\",\n  \"id\",\n  \"bind\",\n  \"init\",\n  \"for\",\n  \"model\",\n  \"modelable\",\n  \"transition\",\n  \"show\",\n  \"if\",\n  DEFAULT,\n  \"teleport\",\n  \"element\"\n];\nfunction byPriority(a, b) {\n  let typeA = directiveOrder.indexOf(a.type) === -1 ? DEFAULT : a.type;\n  let typeB = directiveOrder.indexOf(b.type) === -1 ? DEFAULT : b.type;\n  return directiveOrder.indexOf(typeA) - directiveOrder.indexOf(typeB);\n}\n\n// packages/alpinejs/src/utils/dispatch.js\nfunction dispatch(el, name, detail = {}) {\n  el.dispatchEvent(new CustomEvent(name, {\n    detail,\n    bubbles: true,\n    composed: true,\n    cancelable: true\n  }));\n}\n\n// packages/alpinejs/src/nextTick.js\nvar tickStack = [];\nvar isHolding = false;\nfunction nextTick(callback) {\n  tickStack.push(callback);\n  queueMicrotask(() => {\n    isHolding || setTimeout(() => {\n      releaseNextTicks();\n    });\n  });\n}\nfunction releaseNextTicks() {\n  isHolding = false;\n  while (tickStack.length)\n    tickStack.shift()();\n}\nfunction holdNextTicks() {\n  isHolding = true;\n}\n\n// packages/alpinejs/src/utils/walk.js\nfunction walk(el, callback) {\n  if (typeof ShadowRoot === \"function\" && el instanceof ShadowRoot) {\n    Array.from(el.children).forEach((el2) => walk(el2, callback));\n    return;\n  }\n  let skip = false;\n  callback(el, () => skip = true);\n  if (skip)\n    return;\n  let node = el.firstElementChild;\n  while (node) {\n    walk(node, callback, false);\n    node = node.nextElementSibling;\n  }\n}\n\n// packages/alpinejs/src/utils/warn.js\nfunction warn(message, ...args) {\n  console.warn(`Alpine Warning: ${message}`, ...args);\n}\n\n// packages/alpinejs/src/lifecycle.js\nfunction start() {\n  if (!document.body)\n    warn(\"Unable to initialize. Trying to load Alpine before `<body>` is available. Did you forget to add `defer` in Alpine's `<script>` tag?\");\n  dispatch(document, \"alpine:init\");\n  dispatch(document, \"alpine:initializing\");\n  startObservingMutations();\n  onElAdded((el) => initTree(el, walk));\n  onElRemoved((el) => destroyTree(el));\n  onAttributesAdded((el, attrs) => {\n    directives(el, attrs).forEach((handle) => handle());\n  });\n  let outNestedComponents = (el) => !closestRoot(el.parentElement, true);\n  Array.from(document.querySelectorAll(allSelectors())).filter(outNestedComponents).forEach((el) => {\n    initTree(el);\n  });\n  dispatch(document, \"alpine:initialized\");\n}\nvar rootSelectorCallbacks = [];\nvar initSelectorCallbacks = [];\nfunction rootSelectors() {\n  return rootSelectorCallbacks.map((fn) => fn());\n}\nfunction allSelectors() {\n  return rootSelectorCallbacks.concat(initSelectorCallbacks).map((fn) => fn());\n}\nfunction addRootSelector(selectorCallback) {\n  rootSelectorCallbacks.push(selectorCallback);\n}\nfunction addInitSelector(selectorCallback) {\n  initSelectorCallbacks.push(selectorCallback);\n}\nfunction closestRoot(el, includeInitSelectors = false) {\n  return findClosest(el, (element) => {\n    const selectors = includeInitSelectors ? allSelectors() : rootSelectors();\n    if (selectors.some((selector) => element.matches(selector)))\n      return true;\n  });\n}\nfunction findClosest(el, callback) {\n  if (!el)\n    return;\n  if (callback(el))\n    return el;\n  if (el._x_teleportBack)\n    el = el._x_teleportBack;\n  if (!el.parentElement)\n    return;\n  return findClosest(el.parentElement, callback);\n}\nfunction isRoot(el) {\n  return rootSelectors().some((selector) => el.matches(selector));\n}\nfunction initTree(el, walker = walk) {\n  deferHandlingDirectives(() => {\n    walker(el, (el2, skip) => {\n      directives(el2, el2.attributes).forEach((handle) => handle());\n      el2._x_ignore && skip();\n    });\n  });\n}\nfunction destroyTree(root) {\n  walk(root, (el) => cleanupAttributes(el));\n}\n\n// packages/alpinejs/src/utils/classes.js\nfunction setClasses(el, value) {\n  if (Array.isArray(value)) {\n    return setClassesFromString(el, value.join(\" \"));\n  } else if (typeof value === \"object\" && value !== null) {\n    return setClassesFromObject(el, value);\n  } else if (typeof value === \"function\") {\n    return setClasses(el, value());\n  }\n  return setClassesFromString(el, value);\n}\nfunction setClassesFromString(el, classString) {\n  let split = (classString2) => classString2.split(\" \").filter(Boolean);\n  let missingClasses = (classString2) => classString2.split(\" \").filter((i) => !el.classList.contains(i)).filter(Boolean);\n  let addClassesAndReturnUndo = (classes) => {\n    el.classList.add(...classes);\n    return () => {\n      el.classList.remove(...classes);\n    };\n  };\n  classString = classString === true ? classString = \"\" : classString || \"\";\n  return addClassesAndReturnUndo(missingClasses(classString));\n}\nfunction setClassesFromObject(el, classObject) {\n  let split = (classString) => classString.split(\" \").filter(Boolean);\n  let forAdd = Object.entries(classObject).flatMap(([classString, bool]) => bool ? split(classString) : false).filter(Boolean);\n  let forRemove = Object.entries(classObject).flatMap(([classString, bool]) => !bool ? split(classString) : false).filter(Boolean);\n  let added = [];\n  let removed = [];\n  forRemove.forEach((i) => {\n    if (el.classList.contains(i)) {\n      el.classList.remove(i);\n      removed.push(i);\n    }\n  });\n  forAdd.forEach((i) => {\n    if (!el.classList.contains(i)) {\n      el.classList.add(i);\n      added.push(i);\n    }\n  });\n  return () => {\n    removed.forEach((i) => el.classList.add(i));\n    added.forEach((i) => el.classList.remove(i));\n  };\n}\n\n// packages/alpinejs/src/utils/styles.js\nfunction setStyles(el, value) {\n  if (typeof value === \"object\" && value !== null) {\n    return setStylesFromObject(el, value);\n  }\n  return setStylesFromString(el, value);\n}\nfunction setStylesFromObject(el, value) {\n  let previousStyles = {};\n  Object.entries(value).forEach(([key, value2]) => {\n    previousStyles[key] = el.style[key];\n    if (!key.startsWith(\"--\")) {\n      key = kebabCase(key);\n    }\n    el.style.setProperty(key, value2);\n  });\n  setTimeout(() => {\n    if (el.style.length === 0) {\n      el.removeAttribute(\"style\");\n    }\n  });\n  return () => {\n    setStyles(el, previousStyles);\n  };\n}\nfunction setStylesFromString(el, value) {\n  let cache = el.getAttribute(\"style\", value);\n  el.setAttribute(\"style\", value);\n  return () => {\n    el.setAttribute(\"style\", cache || \"\");\n  };\n}\nfunction kebabCase(subject) {\n  return subject.replace(/([a-z])([A-Z])/g, \"$1-$2\").toLowerCase();\n}\n\n// packages/alpinejs/src/utils/once.js\nfunction once(callback, fallback = () => {\n}) {\n  let called = false;\n  return function() {\n    if (!called) {\n      called = true;\n      callback.apply(this, arguments);\n    } else {\n      fallback.apply(this, arguments);\n    }\n  };\n}\n\n// packages/alpinejs/src/directives/x-transition.js\ndirective(\"transition\", (el, {value, modifiers, expression}, {evaluate: evaluate2}) => {\n  if (typeof expression === \"function\")\n    expression = evaluate2(expression);\n  if (!expression) {\n    registerTransitionsFromHelper(el, modifiers, value);\n  } else {\n    registerTransitionsFromClassString(el, expression, value);\n  }\n});\nfunction registerTransitionsFromClassString(el, classString, stage) {\n  registerTransitionObject(el, setClasses, \"\");\n  let directiveStorageMap = {\n    enter: (classes) => {\n      el._x_transition.enter.during = classes;\n    },\n    \"enter-start\": (classes) => {\n      el._x_transition.enter.start = classes;\n    },\n    \"enter-end\": (classes) => {\n      el._x_transition.enter.end = classes;\n    },\n    leave: (classes) => {\n      el._x_transition.leave.during = classes;\n    },\n    \"leave-start\": (classes) => {\n      el._x_transition.leave.start = classes;\n    },\n    \"leave-end\": (classes) => {\n      el._x_transition.leave.end = classes;\n    }\n  };\n  directiveStorageMap[stage](classString);\n}\nfunction registerTransitionsFromHelper(el, modifiers, stage) {\n  registerTransitionObject(el, setStyles);\n  let doesntSpecify = !modifiers.includes(\"in\") && !modifiers.includes(\"out\") && !stage;\n  let transitioningIn = doesntSpecify || modifiers.includes(\"in\") || [\"enter\"].includes(stage);\n  let transitioningOut = doesntSpecify || modifiers.includes(\"out\") || [\"leave\"].includes(stage);\n  if (modifiers.includes(\"in\") && !doesntSpecify) {\n    modifiers = modifiers.filter((i, index) => index < modifiers.indexOf(\"out\"));\n  }\n  if (modifiers.includes(\"out\") && !doesntSpecify) {\n    modifiers = modifiers.filter((i, index) => index > modifiers.indexOf(\"out\"));\n  }\n  let wantsAll = !modifiers.includes(\"opacity\") && !modifiers.includes(\"scale\");\n  let wantsOpacity = wantsAll || modifiers.includes(\"opacity\");\n  let wantsScale = wantsAll || modifiers.includes(\"scale\");\n  let opacityValue = wantsOpacity ? 0 : 1;\n  let scaleValue = wantsScale ? modifierValue(modifiers, \"scale\", 95) / 100 : 1;\n  let delay = modifierValue(modifiers, \"delay\", 0);\n  let origin = modifierValue(modifiers, \"origin\", \"center\");\n  let property = \"opacity, transform\";\n  let durationIn = modifierValue(modifiers, \"duration\", 150) / 1e3;\n  let durationOut = modifierValue(modifiers, \"duration\", 75) / 1e3;\n  let easing = `cubic-bezier(0.4, 0.0, 0.2, 1)`;\n  if (transitioningIn) {\n    el._x_transition.enter.during = {\n      transformOrigin: origin,\n      transitionDelay: delay,\n      transitionProperty: property,\n      transitionDuration: `${durationIn}s`,\n      transitionTimingFunction: easing\n    };\n    el._x_transition.enter.start = {\n      opacity: opacityValue,\n      transform: `scale(${scaleValue})`\n    };\n    el._x_transition.enter.end = {\n      opacity: 1,\n      transform: `scale(1)`\n    };\n  }\n  if (transitioningOut) {\n    el._x_transition.leave.during = {\n      transformOrigin: origin,\n      transitionDelay: delay,\n      transitionProperty: property,\n      transitionDuration: `${durationOut}s`,\n      transitionTimingFunction: easing\n    };\n    el._x_transition.leave.start = {\n      opacity: 1,\n      transform: `scale(1)`\n    };\n    el._x_transition.leave.end = {\n      opacity: opacityValue,\n      transform: `scale(${scaleValue})`\n    };\n  }\n}\nfunction registerTransitionObject(el, setFunction, defaultValue = {}) {\n  if (!el._x_transition)\n    el._x_transition = {\n      enter: {during: defaultValue, start: defaultValue, end: defaultValue},\n      leave: {during: defaultValue, start: defaultValue, end: defaultValue},\n      in(before = () => {\n      }, after = () => {\n      }) {\n        transition(el, setFunction, {\n          during: this.enter.during,\n          start: this.enter.start,\n          end: this.enter.end\n        }, before, after);\n      },\n      out(before = () => {\n      }, after = () => {\n      }) {\n        transition(el, setFunction, {\n          during: this.leave.during,\n          start: this.leave.start,\n          end: this.leave.end\n        }, before, after);\n      }\n    };\n}\nwindow.Element.prototype._x_toggleAndCascadeWithTransitions = function(el, value, show, hide) {\n  let clickAwayCompatibleShow = () => {\n    document.visibilityState === \"visible\" ? requestAnimationFrame(show) : setTimeout(show);\n  };\n  if (value) {\n    if (el._x_transition && (el._x_transition.enter || el._x_transition.leave)) {\n      el._x_transition.enter && (Object.entries(el._x_transition.enter.during).length || Object.entries(el._x_transition.enter.start).length || Object.entries(el._x_transition.enter.end).length) ? el._x_transition.in(show) : clickAwayCompatibleShow();\n    } else {\n      el._x_transition ? el._x_transition.in(show) : clickAwayCompatibleShow();\n    }\n    return;\n  }\n  el._x_hidePromise = el._x_transition ? new Promise((resolve, reject) => {\n    el._x_transition.out(() => {\n    }, () => resolve(hide));\n    el._x_transitioning.beforeCancel(() => reject({isFromCancelledTransition: true}));\n  }) : Promise.resolve(hide);\n  queueMicrotask(() => {\n    let closest = closestHide(el);\n    if (closest) {\n      if (!closest._x_hideChildren)\n        closest._x_hideChildren = [];\n      closest._x_hideChildren.push(el);\n    } else {\n      queueMicrotask(() => {\n        let hideAfterChildren = (el2) => {\n          let carry = Promise.all([\n            el2._x_hidePromise,\n            ...(el2._x_hideChildren || []).map(hideAfterChildren)\n          ]).then(([i]) => i());\n          delete el2._x_hidePromise;\n          delete el2._x_hideChildren;\n          return carry;\n        };\n        hideAfterChildren(el).catch((e) => {\n          if (!e.isFromCancelledTransition)\n            throw e;\n        });\n      });\n    }\n  });\n};\nfunction closestHide(el) {\n  let parent = el.parentNode;\n  if (!parent)\n    return;\n  return parent._x_hidePromise ? parent : closestHide(parent);\n}\nfunction transition(el, setFunction, {during, start: start2, end} = {}, before = () => {\n}, after = () => {\n}) {\n  if (el._x_transitioning)\n    el._x_transitioning.cancel();\n  if (Object.keys(during).length === 0 && Object.keys(start2).length === 0 && Object.keys(end).length === 0) {\n    before();\n    after();\n    return;\n  }\n  let undoStart, undoDuring, undoEnd;\n  performTransition(el, {\n    start() {\n      undoStart = setFunction(el, start2);\n    },\n    during() {\n      undoDuring = setFunction(el, during);\n    },\n    before,\n    end() {\n      undoStart();\n      undoEnd = setFunction(el, end);\n    },\n    after,\n    cleanup() {\n      undoDuring();\n      undoEnd();\n    }\n  });\n}\nfunction performTransition(el, stages) {\n  let interrupted, reachedBefore, reachedEnd;\n  let finish = once(() => {\n    mutateDom(() => {\n      interrupted = true;\n      if (!reachedBefore)\n        stages.before();\n      if (!reachedEnd) {\n        stages.end();\n        releaseNextTicks();\n      }\n      stages.after();\n      if (el.isConnected)\n        stages.cleanup();\n      delete el._x_transitioning;\n    });\n  });\n  el._x_transitioning = {\n    beforeCancels: [],\n    beforeCancel(callback) {\n      this.beforeCancels.push(callback);\n    },\n    cancel: once(function() {\n      while (this.beforeCancels.length) {\n        this.beforeCancels.shift()();\n      }\n      ;\n      finish();\n    }),\n    finish\n  };\n  mutateDom(() => {\n    stages.start();\n    stages.during();\n  });\n  holdNextTicks();\n  requestAnimationFrame(() => {\n    if (interrupted)\n      return;\n    let duration = Number(getComputedStyle(el).transitionDuration.replace(/,.*/, \"\").replace(\"s\", \"\")) * 1e3;\n    let delay = Number(getComputedStyle(el).transitionDelay.replace(/,.*/, \"\").replace(\"s\", \"\")) * 1e3;\n    if (duration === 0)\n      duration = Number(getComputedStyle(el).animationDuration.replace(\"s\", \"\")) * 1e3;\n    mutateDom(() => {\n      stages.before();\n    });\n    reachedBefore = true;\n    requestAnimationFrame(() => {\n      if (interrupted)\n        return;\n      mutateDom(() => {\n        stages.end();\n      });\n      releaseNextTicks();\n      setTimeout(el._x_transitioning.finish, duration + delay);\n      reachedEnd = true;\n    });\n  });\n}\nfunction modifierValue(modifiers, key, fallback) {\n  if (modifiers.indexOf(key) === -1)\n    return fallback;\n  const rawValue = modifiers[modifiers.indexOf(key) + 1];\n  if (!rawValue)\n    return fallback;\n  if (key === \"scale\") {\n    if (isNaN(rawValue))\n      return fallback;\n  }\n  if (key === \"duration\") {\n    let match = rawValue.match(/([0-9]+)ms/);\n    if (match)\n      return match[1];\n  }\n  if (key === \"origin\") {\n    if ([\"top\", \"right\", \"left\", \"center\", \"bottom\"].includes(modifiers[modifiers.indexOf(key) + 2])) {\n      return [rawValue, modifiers[modifiers.indexOf(key) + 2]].join(\" \");\n    }\n  }\n  return rawValue;\n}\n\n// packages/alpinejs/src/clone.js\nvar isCloning = false;\nfunction skipDuringClone(callback, fallback = () => {\n}) {\n  return (...args) => isCloning ? fallback(...args) : callback(...args);\n}\nfunction clone(oldEl, newEl) {\n  if (!newEl._x_dataStack)\n    newEl._x_dataStack = oldEl._x_dataStack;\n  isCloning = true;\n  dontRegisterReactiveSideEffects(() => {\n    cloneTree(newEl);\n  });\n  isCloning = false;\n}\nfunction cloneTree(el) {\n  let hasRunThroughFirstEl = false;\n  let shallowWalker = (el2, callback) => {\n    walk(el2, (el3, skip) => {\n      if (hasRunThroughFirstEl && isRoot(el3))\n        return skip();\n      hasRunThroughFirstEl = true;\n      callback(el3, skip);\n    });\n  };\n  initTree(el, shallowWalker);\n}\nfunction dontRegisterReactiveSideEffects(callback) {\n  let cache = effect;\n  overrideEffect((callback2, el) => {\n    let storedEffect = cache(callback2);\n    release(storedEffect);\n    return () => {\n    };\n  });\n  callback();\n  overrideEffect(cache);\n}\n\n// packages/alpinejs/src/utils/bind.js\nfunction bind(el, name, value, modifiers = []) {\n  if (!el._x_bindings)\n    el._x_bindings = reactive({});\n  el._x_bindings[name] = value;\n  name = modifiers.includes(\"camel\") ? camelCase(name) : name;\n  switch (name) {\n    case \"value\":\n      bindInputValue(el, value);\n      break;\n    case \"style\":\n      bindStyles(el, value);\n      break;\n    case \"class\":\n      bindClasses(el, value);\n      break;\n    default:\n      bindAttribute(el, name, value);\n      break;\n  }\n}\nfunction bindInputValue(el, value) {\n  if (el.type === \"radio\") {\n    if (el.attributes.value === void 0) {\n      el.value = value;\n    }\n    if (window.fromModel) {\n      el.checked = checkedAttrLooseCompare(el.value, value);\n    }\n  } else if (el.type === \"checkbox\") {\n    if (Number.isInteger(value)) {\n      el.value = value;\n    } else if (!Number.isInteger(value) && !Array.isArray(value) && typeof value !== \"boolean\" && ![null, void 0].includes(value)) {\n      el.value = String(value);\n    } else {\n      if (Array.isArray(value)) {\n        el.checked = value.some((val) => checkedAttrLooseCompare(val, el.value));\n      } else {\n        el.checked = !!value;\n      }\n    }\n  } else if (el.tagName === \"SELECT\") {\n    updateSelect(el, value);\n  } else {\n    if (el.value === value)\n      return;\n    el.value = value;\n  }\n}\nfunction bindClasses(el, value) {\n  if (el._x_undoAddedClasses)\n    el._x_undoAddedClasses();\n  el._x_undoAddedClasses = setClasses(el, value);\n}\nfunction bindStyles(el, value) {\n  if (el._x_undoAddedStyles)\n    el._x_undoAddedStyles();\n  el._x_undoAddedStyles = setStyles(el, value);\n}\nfunction bindAttribute(el, name, value) {\n  if ([null, void 0, false].includes(value) && attributeShouldntBePreservedIfFalsy(name)) {\n    el.removeAttribute(name);\n  } else {\n    if (isBooleanAttr(name))\n      value = name;\n    setIfChanged(el, name, value);\n  }\n}\nfunction setIfChanged(el, attrName, value) {\n  if (el.getAttribute(attrName) != value) {\n    el.setAttribute(attrName, value);\n  }\n}\nfunction updateSelect(el, value) {\n  const arrayWrappedValue = [].concat(value).map((value2) => {\n    return value2 + \"\";\n  });\n  Array.from(el.options).forEach((option) => {\n    option.selected = arrayWrappedValue.includes(option.value);\n  });\n}\nfunction camelCase(subject) {\n  return subject.toLowerCase().replace(/-(\\w)/g, (match, char) => char.toUpperCase());\n}\nfunction checkedAttrLooseCompare(valueA, valueB) {\n  return valueA == valueB;\n}\nfunction isBooleanAttr(attrName) {\n  const booleanAttributes = [\n    \"disabled\",\n    \"checked\",\n    \"required\",\n    \"readonly\",\n    \"hidden\",\n    \"open\",\n    \"selected\",\n    \"autofocus\",\n    \"itemscope\",\n    \"multiple\",\n    \"novalidate\",\n    \"allowfullscreen\",\n    \"allowpaymentrequest\",\n    \"formnovalidate\",\n    \"autoplay\",\n    \"controls\",\n    \"loop\",\n    \"muted\",\n    \"playsinline\",\n    \"default\",\n    \"ismap\",\n    \"reversed\",\n    \"async\",\n    \"defer\",\n    \"nomodule\"\n  ];\n  return booleanAttributes.includes(attrName);\n}\nfunction attributeShouldntBePreservedIfFalsy(name) {\n  return ![\"aria-pressed\", \"aria-checked\", \"aria-expanded\", \"aria-selected\"].includes(name);\n}\nfunction getBinding(el, name, fallback) {\n  if (el._x_bindings && el._x_bindings[name] !== void 0)\n    return el._x_bindings[name];\n  let attr = el.getAttribute(name);\n  if (attr === null)\n    return typeof fallback === \"function\" ? fallback() : fallback;\n  if (isBooleanAttr(name)) {\n    return !![name, \"true\"].includes(attr);\n  }\n  if (attr === \"\")\n    return true;\n  return attr;\n}\n\n// packages/alpinejs/src/utils/debounce.js\nfunction debounce(func, wait) {\n  var timeout;\n  return function() {\n    var context = this, args = arguments;\n    var later = function() {\n      timeout = null;\n      func.apply(context, args);\n    };\n    clearTimeout(timeout);\n    timeout = setTimeout(later, wait);\n  };\n}\n\n// packages/alpinejs/src/utils/throttle.js\nfunction throttle(func, limit) {\n  let inThrottle;\n  return function() {\n    let context = this, args = arguments;\n    if (!inThrottle) {\n      func.apply(context, args);\n      inThrottle = true;\n      setTimeout(() => inThrottle = false, limit);\n    }\n  };\n}\n\n// packages/alpinejs/src/plugin.js\nfunction plugin(callback) {\n  callback(alpine_default);\n}\n\n// packages/alpinejs/src/store.js\nvar stores = {};\nvar isReactive = false;\nfunction store(name, value) {\n  if (!isReactive) {\n    stores = reactive(stores);\n    isReactive = true;\n  }\n  if (value === void 0) {\n    return stores[name];\n  }\n  stores[name] = value;\n  if (typeof value === \"object\" && value !== null && value.hasOwnProperty(\"init\") && typeof value.init === \"function\") {\n    stores[name].init();\n  }\n  initInterceptors(stores[name]);\n}\nfunction getStores() {\n  return stores;\n}\n\n// packages/alpinejs/src/binds.js\nvar binds = {};\nfunction bind2(name, object) {\n  binds[name] = typeof object !== \"function\" ? () => object : object;\n}\nfunction injectBindingProviders(obj) {\n  Object.entries(binds).forEach(([name, callback]) => {\n    Object.defineProperty(obj, name, {\n      get() {\n        return (...args) => {\n          return callback(...args);\n        };\n      }\n    });\n  });\n  return obj;\n}\n\n// packages/alpinejs/src/datas.js\nvar datas = {};\nfunction data(name, callback) {\n  datas[name] = callback;\n}\nfunction injectDataProviders(obj, context) {\n  Object.entries(datas).forEach(([name, callback]) => {\n    Object.defineProperty(obj, name, {\n      get() {\n        return (...args) => {\n          return callback.bind(context)(...args);\n        };\n      },\n      enumerable: false\n    });\n  });\n  return obj;\n}\n\n// packages/alpinejs/src/alpine.js\nvar Alpine = {\n  get reactive() {\n    return reactive;\n  },\n  get release() {\n    return release;\n  },\n  get effect() {\n    return effect;\n  },\n  get raw() {\n    return raw;\n  },\n  version: \"3.9.5\",\n  flushAndStopDeferringMutations,\n  disableEffectScheduling,\n  setReactivityEngine,\n  closestDataStack,\n  skipDuringClone,\n  addRootSelector,\n  addInitSelector,\n  addScopeToNode,\n  deferMutations,\n  mapAttributes,\n  evaluateLater,\n  setEvaluator,\n  mergeProxies,\n  findClosest,\n  closestRoot,\n  interceptor,\n  transition,\n  setStyles,\n  mutateDom,\n  directive,\n  throttle,\n  debounce,\n  evaluate,\n  initTree,\n  nextTick,\n  prefixed: prefix,\n  prefix: setPrefix,\n  plugin,\n  magic,\n  store,\n  start,\n  clone,\n  bound: getBinding,\n  $data: scope,\n  data,\n  bind: bind2\n};\nvar alpine_default = Alpine;\n\n// node_modules/@vue/shared/dist/shared.esm-bundler.js\nfunction makeMap(str, expectsLowerCase) {\n  const map = Object.create(null);\n  const list = str.split(\",\");\n  for (let i = 0; i < list.length; i++) {\n    map[list[i]] = true;\n  }\n  return expectsLowerCase ? (val) => !!map[val.toLowerCase()] : (val) => !!map[val];\n}\nvar PatchFlagNames = {\n  [1]: `TEXT`,\n  [2]: `CLASS`,\n  [4]: `STYLE`,\n  [8]: `PROPS`,\n  [16]: `FULL_PROPS`,\n  [32]: `HYDRATE_EVENTS`,\n  [64]: `STABLE_FRAGMENT`,\n  [128]: `KEYED_FRAGMENT`,\n  [256]: `UNKEYED_FRAGMENT`,\n  [512]: `NEED_PATCH`,\n  [1024]: `DYNAMIC_SLOTS`,\n  [2048]: `DEV_ROOT_FRAGMENT`,\n  [-1]: `HOISTED`,\n  [-2]: `BAIL`\n};\nvar slotFlagsText = {\n  [1]: \"STABLE\",\n  [2]: \"DYNAMIC\",\n  [3]: \"FORWARDED\"\n};\nvar specialBooleanAttrs = `itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly`;\nvar isBooleanAttr2 = /* @__PURE__ */ makeMap(specialBooleanAttrs + `,async,autofocus,autoplay,controls,default,defer,disabled,hidden,loop,open,required,reversed,scoped,seamless,checked,muted,multiple,selected`);\nvar EMPTY_OBJ = true ? Object.freeze({}) : {};\nvar EMPTY_ARR = true ? Object.freeze([]) : [];\nvar extend = Object.assign;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nvar hasOwn = (val, key) => hasOwnProperty.call(val, key);\nvar isArray = Array.isArray;\nvar isMap = (val) => toTypeString(val) === \"[object Map]\";\nvar isString = (val) => typeof val === \"string\";\nvar isSymbol = (val) => typeof val === \"symbol\";\nvar isObject = (val) => val !== null && typeof val === \"object\";\nvar objectToString = Object.prototype.toString;\nvar toTypeString = (value) => objectToString.call(value);\nvar toRawType = (value) => {\n  return toTypeString(value).slice(8, -1);\n};\nvar isIntegerKey = (key) => isString(key) && key !== \"NaN\" && key[0] !== \"-\" && \"\" + parseInt(key, 10) === key;\nvar cacheStringFunction = (fn) => {\n  const cache = Object.create(null);\n  return (str) => {\n    const hit = cache[str];\n    return hit || (cache[str] = fn(str));\n  };\n};\nvar camelizeRE = /-(\\w)/g;\nvar camelize = cacheStringFunction((str) => {\n  return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : \"\");\n});\nvar hyphenateRE = /\\B([A-Z])/g;\nvar hyphenate = cacheStringFunction((str) => str.replace(hyphenateRE, \"-$1\").toLowerCase());\nvar capitalize = cacheStringFunction((str) => str.charAt(0).toUpperCase() + str.slice(1));\nvar toHandlerKey = cacheStringFunction((str) => str ? `on${capitalize(str)}` : ``);\nvar hasChanged = (value, oldValue) => value !== oldValue && (value === value || oldValue === oldValue);\n\n// node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js\nvar targetMap = new WeakMap();\nvar effectStack = [];\nvar activeEffect;\nvar ITERATE_KEY = Symbol(true ? \"iterate\" : \"\");\nvar MAP_KEY_ITERATE_KEY = Symbol(true ? \"Map key iterate\" : \"\");\nfunction isEffect(fn) {\n  return fn && fn._isEffect === true;\n}\nfunction effect2(fn, options = EMPTY_OBJ) {\n  if (isEffect(fn)) {\n    fn = fn.raw;\n  }\n  const effect3 = createReactiveEffect(fn, options);\n  if (!options.lazy) {\n    effect3();\n  }\n  return effect3;\n}\nfunction stop(effect3) {\n  if (effect3.active) {\n    cleanup(effect3);\n    if (effect3.options.onStop) {\n      effect3.options.onStop();\n    }\n    effect3.active = false;\n  }\n}\nvar uid = 0;\nfunction createReactiveEffect(fn, options) {\n  const effect3 = function reactiveEffect() {\n    if (!effect3.active) {\n      return fn();\n    }\n    if (!effectStack.includes(effect3)) {\n      cleanup(effect3);\n      try {\n        enableTracking();\n        effectStack.push(effect3);\n        activeEffect = effect3;\n        return fn();\n      } finally {\n        effectStack.pop();\n        resetTracking();\n        activeEffect = effectStack[effectStack.length - 1];\n      }\n    }\n  };\n  effect3.id = uid++;\n  effect3.allowRecurse = !!options.allowRecurse;\n  effect3._isEffect = true;\n  effect3.active = true;\n  effect3.raw = fn;\n  effect3.deps = [];\n  effect3.options = options;\n  return effect3;\n}\nfunction cleanup(effect3) {\n  const {deps} = effect3;\n  if (deps.length) {\n    for (let i = 0; i < deps.length; i++) {\n      deps[i].delete(effect3);\n    }\n    deps.length = 0;\n  }\n}\nvar shouldTrack = true;\nvar trackStack = [];\nfunction pauseTracking() {\n  trackStack.push(shouldTrack);\n  shouldTrack = false;\n}\nfunction enableTracking() {\n  trackStack.push(shouldTrack);\n  shouldTrack = true;\n}\nfunction resetTracking() {\n  const last = trackStack.pop();\n  shouldTrack = last === void 0 ? true : last;\n}\nfunction track(target, type, key) {\n  if (!shouldTrack || activeEffect === void 0) {\n    return;\n  }\n  let depsMap = targetMap.get(target);\n  if (!depsMap) {\n    targetMap.set(target, depsMap = new Map());\n  }\n  let dep = depsMap.get(key);\n  if (!dep) {\n    depsMap.set(key, dep = new Set());\n  }\n  if (!dep.has(activeEffect)) {\n    dep.add(activeEffect);\n    activeEffect.deps.push(dep);\n    if (activeEffect.options.onTrack) {\n      activeEffect.options.onTrack({\n        effect: activeEffect,\n        target,\n        type,\n        key\n      });\n    }\n  }\n}\nfunction trigger(target, type, key, newValue, oldValue, oldTarget) {\n  const depsMap = targetMap.get(target);\n  if (!depsMap) {\n    return;\n  }\n  const effects = new Set();\n  const add2 = (effectsToAdd) => {\n    if (effectsToAdd) {\n      effectsToAdd.forEach((effect3) => {\n        if (effect3 !== activeEffect || effect3.allowRecurse) {\n          effects.add(effect3);\n        }\n      });\n    }\n  };\n  if (type === \"clear\") {\n    depsMap.forEach(add2);\n  } else if (key === \"length\" && isArray(target)) {\n    depsMap.forEach((dep, key2) => {\n      if (key2 === \"length\" || key2 >= newValue) {\n        add2(dep);\n      }\n    });\n  } else {\n    if (key !== void 0) {\n      add2(depsMap.get(key));\n    }\n    switch (type) {\n      case \"add\":\n        if (!isArray(target)) {\n          add2(depsMap.get(ITERATE_KEY));\n          if (isMap(target)) {\n            add2(depsMap.get(MAP_KEY_ITERATE_KEY));\n          }\n        } else if (isIntegerKey(key)) {\n          add2(depsMap.get(\"length\"));\n        }\n        break;\n      case \"delete\":\n        if (!isArray(target)) {\n          add2(depsMap.get(ITERATE_KEY));\n          if (isMap(target)) {\n            add2(depsMap.get(MAP_KEY_ITERATE_KEY));\n          }\n        }\n        break;\n      case \"set\":\n        if (isMap(target)) {\n          add2(depsMap.get(ITERATE_KEY));\n        }\n        break;\n    }\n  }\n  const run = (effect3) => {\n    if (effect3.options.onTrigger) {\n      effect3.options.onTrigger({\n        effect: effect3,\n        target,\n        key,\n        type,\n        newValue,\n        oldValue,\n        oldTarget\n      });\n    }\n    if (effect3.options.scheduler) {\n      effect3.options.scheduler(effect3);\n    } else {\n      effect3();\n    }\n  };\n  effects.forEach(run);\n}\nvar isNonTrackableKeys = /* @__PURE__ */ makeMap(`__proto__,__v_isRef,__isVue`);\nvar builtInSymbols = new Set(Object.getOwnPropertyNames(Symbol).map((key) => Symbol[key]).filter(isSymbol));\nvar get2 = /* @__PURE__ */ createGetter();\nvar shallowGet = /* @__PURE__ */ createGetter(false, true);\nvar readonlyGet = /* @__PURE__ */ createGetter(true);\nvar shallowReadonlyGet = /* @__PURE__ */ createGetter(true, true);\nvar arrayInstrumentations = {};\n[\"includes\", \"indexOf\", \"lastIndexOf\"].forEach((key) => {\n  const method = Array.prototype[key];\n  arrayInstrumentations[key] = function(...args) {\n    const arr = toRaw(this);\n    for (let i = 0, l = this.length; i < l; i++) {\n      track(arr, \"get\", i + \"\");\n    }\n    const res = method.apply(arr, args);\n    if (res === -1 || res === false) {\n      return method.apply(arr, args.map(toRaw));\n    } else {\n      return res;\n    }\n  };\n});\n[\"push\", \"pop\", \"shift\", \"unshift\", \"splice\"].forEach((key) => {\n  const method = Array.prototype[key];\n  arrayInstrumentations[key] = function(...args) {\n    pauseTracking();\n    const res = method.apply(this, args);\n    resetTracking();\n    return res;\n  };\n});\nfunction createGetter(isReadonly = false, shallow = false) {\n  return function get3(target, key, receiver) {\n    if (key === \"__v_isReactive\") {\n      return !isReadonly;\n    } else if (key === \"__v_isReadonly\") {\n      return isReadonly;\n    } else if (key === \"__v_raw\" && receiver === (isReadonly ? shallow ? shallowReadonlyMap : readonlyMap : shallow ? shallowReactiveMap : reactiveMap).get(target)) {\n      return target;\n    }\n    const targetIsArray = isArray(target);\n    if (!isReadonly && targetIsArray && hasOwn(arrayInstrumentations, key)) {\n      return Reflect.get(arrayInstrumentations, key, receiver);\n    }\n    const res = Reflect.get(target, key, receiver);\n    if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) {\n      return res;\n    }\n    if (!isReadonly) {\n      track(target, \"get\", key);\n    }\n    if (shallow) {\n      return res;\n    }\n    if (isRef(res)) {\n      const shouldUnwrap = !targetIsArray || !isIntegerKey(key);\n      return shouldUnwrap ? res.value : res;\n    }\n    if (isObject(res)) {\n      return isReadonly ? readonly(res) : reactive2(res);\n    }\n    return res;\n  };\n}\nvar set2 = /* @__PURE__ */ createSetter();\nvar shallowSet = /* @__PURE__ */ createSetter(true);\nfunction createSetter(shallow = false) {\n  return function set3(target, key, value, receiver) {\n    let oldValue = target[key];\n    if (!shallow) {\n      value = toRaw(value);\n      oldValue = toRaw(oldValue);\n      if (!isArray(target) && isRef(oldValue) && !isRef(value)) {\n        oldValue.value = value;\n        return true;\n      }\n    }\n    const hadKey = isArray(target) && isIntegerKey(key) ? Number(key) < target.length : hasOwn(target, key);\n    const result = Reflect.set(target, key, value, receiver);\n    if (target === toRaw(receiver)) {\n      if (!hadKey) {\n        trigger(target, \"add\", key, value);\n      } else if (hasChanged(value, oldValue)) {\n        trigger(target, \"set\", key, value, oldValue);\n      }\n    }\n    return result;\n  };\n}\nfunction deleteProperty(target, key) {\n  const hadKey = hasOwn(target, key);\n  const oldValue = target[key];\n  const result = Reflect.deleteProperty(target, key);\n  if (result && hadKey) {\n    trigger(target, \"delete\", key, void 0, oldValue);\n  }\n  return result;\n}\nfunction has(target, key) {\n  const result = Reflect.has(target, key);\n  if (!isSymbol(key) || !builtInSymbols.has(key)) {\n    track(target, \"has\", key);\n  }\n  return result;\n}\nfunction ownKeys(target) {\n  track(target, \"iterate\", isArray(target) ? \"length\" : ITERATE_KEY);\n  return Reflect.ownKeys(target);\n}\nvar mutableHandlers = {\n  get: get2,\n  set: set2,\n  deleteProperty,\n  has,\n  ownKeys\n};\nvar readonlyHandlers = {\n  get: readonlyGet,\n  set(target, key) {\n    if (true) {\n      console.warn(`Set operation on key \"${String(key)}\" failed: target is readonly.`, target);\n    }\n    return true;\n  },\n  deleteProperty(target, key) {\n    if (true) {\n      console.warn(`Delete operation on key \"${String(key)}\" failed: target is readonly.`, target);\n    }\n    return true;\n  }\n};\nvar shallowReactiveHandlers = extend({}, mutableHandlers, {\n  get: shallowGet,\n  set: shallowSet\n});\nvar shallowReadonlyHandlers = extend({}, readonlyHandlers, {\n  get: shallowReadonlyGet\n});\nvar toReactive = (value) => isObject(value) ? reactive2(value) : value;\nvar toReadonly = (value) => isObject(value) ? readonly(value) : value;\nvar toShallow = (value) => value;\nvar getProto = (v) => Reflect.getPrototypeOf(v);\nfunction get$1(target, key, isReadonly = false, isShallow = false) {\n  target = target[\"__v_raw\"];\n  const rawTarget = toRaw(target);\n  const rawKey = toRaw(key);\n  if (key !== rawKey) {\n    !isReadonly && track(rawTarget, \"get\", key);\n  }\n  !isReadonly && track(rawTarget, \"get\", rawKey);\n  const {has: has2} = getProto(rawTarget);\n  const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive;\n  if (has2.call(rawTarget, key)) {\n    return wrap(target.get(key));\n  } else if (has2.call(rawTarget, rawKey)) {\n    return wrap(target.get(rawKey));\n  } else if (target !== rawTarget) {\n    target.get(key);\n  }\n}\nfunction has$1(key, isReadonly = false) {\n  const target = this[\"__v_raw\"];\n  const rawTarget = toRaw(target);\n  const rawKey = toRaw(key);\n  if (key !== rawKey) {\n    !isReadonly && track(rawTarget, \"has\", key);\n  }\n  !isReadonly && track(rawTarget, \"has\", rawKey);\n  return key === rawKey ? target.has(key) : target.has(key) || target.has(rawKey);\n}\nfunction size(target, isReadonly = false) {\n  target = target[\"__v_raw\"];\n  !isReadonly && track(toRaw(target), \"iterate\", ITERATE_KEY);\n  return Reflect.get(target, \"size\", target);\n}\nfunction add(value) {\n  value = toRaw(value);\n  const target = toRaw(this);\n  const proto = getProto(target);\n  const hadKey = proto.has.call(target, value);\n  if (!hadKey) {\n    target.add(value);\n    trigger(target, \"add\", value, value);\n  }\n  return this;\n}\nfunction set$1(key, value) {\n  value = toRaw(value);\n  const target = toRaw(this);\n  const {has: has2, get: get3} = getProto(target);\n  let hadKey = has2.call(target, key);\n  if (!hadKey) {\n    key = toRaw(key);\n    hadKey = has2.call(target, key);\n  } else if (true) {\n    checkIdentityKeys(target, has2, key);\n  }\n  const oldValue = get3.call(target, key);\n  target.set(key, value);\n  if (!hadKey) {\n    trigger(target, \"add\", key, value);\n  } else if (hasChanged(value, oldValue)) {\n    trigger(target, \"set\", key, value, oldValue);\n  }\n  return this;\n}\nfunction deleteEntry(key) {\n  const target = toRaw(this);\n  const {has: has2, get: get3} = getProto(target);\n  let hadKey = has2.call(target, key);\n  if (!hadKey) {\n    key = toRaw(key);\n    hadKey = has2.call(target, key);\n  } else if (true) {\n    checkIdentityKeys(target, has2, key);\n  }\n  const oldValue = get3 ? get3.call(target, key) : void 0;\n  const result = target.delete(key);\n  if (hadKey) {\n    trigger(target, \"delete\", key, void 0, oldValue);\n  }\n  return result;\n}\nfunction clear() {\n  const target = toRaw(this);\n  const hadItems = target.size !== 0;\n  const oldTarget = true ? isMap(target) ? new Map(target) : new Set(target) : void 0;\n  const result = target.clear();\n  if (hadItems) {\n    trigger(target, \"clear\", void 0, void 0, oldTarget);\n  }\n  return result;\n}\nfunction createForEach(isReadonly, isShallow) {\n  return function forEach(callback, thisArg) {\n    const observed = this;\n    const target = observed[\"__v_raw\"];\n    const rawTarget = toRaw(target);\n    const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive;\n    !isReadonly && track(rawTarget, \"iterate\", ITERATE_KEY);\n    return target.forEach((value, key) => {\n      return callback.call(thisArg, wrap(value), wrap(key), observed);\n    });\n  };\n}\nfunction createIterableMethod(method, isReadonly, isShallow) {\n  return function(...args) {\n    const target = this[\"__v_raw\"];\n    const rawTarget = toRaw(target);\n    const targetIsMap = isMap(rawTarget);\n    const isPair = method === \"entries\" || method === Symbol.iterator && targetIsMap;\n    const isKeyOnly = method === \"keys\" && targetIsMap;\n    const innerIterator = target[method](...args);\n    const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive;\n    !isReadonly && track(rawTarget, \"iterate\", isKeyOnly ? MAP_KEY_ITERATE_KEY : ITERATE_KEY);\n    return {\n      next() {\n        const {value, done} = innerIterator.next();\n        return done ? {value, done} : {\n          value: isPair ? [wrap(value[0]), wrap(value[1])] : wrap(value),\n          done\n        };\n      },\n      [Symbol.iterator]() {\n        return this;\n      }\n    };\n  };\n}\nfunction createReadonlyMethod(type) {\n  return function(...args) {\n    if (true) {\n      const key = args[0] ? `on key \"${args[0]}\" ` : ``;\n      console.warn(`${capitalize(type)} operation ${key}failed: target is readonly.`, toRaw(this));\n    }\n    return type === \"delete\" ? false : this;\n  };\n}\nvar mutableInstrumentations = {\n  get(key) {\n    return get$1(this, key);\n  },\n  get size() {\n    return size(this);\n  },\n  has: has$1,\n  add,\n  set: set$1,\n  delete: deleteEntry,\n  clear,\n  forEach: createForEach(false, false)\n};\nvar shallowInstrumentations = {\n  get(key) {\n    return get$1(this, key, false, true);\n  },\n  get size() {\n    return size(this);\n  },\n  has: has$1,\n  add,\n  set: set$1,\n  delete: deleteEntry,\n  clear,\n  forEach: createForEach(false, true)\n};\nvar readonlyInstrumentations = {\n  get(key) {\n    return get$1(this, key, true);\n  },\n  get size() {\n    return size(this, true);\n  },\n  has(key) {\n    return has$1.call(this, key, true);\n  },\n  add: createReadonlyMethod(\"add\"),\n  set: createReadonlyMethod(\"set\"),\n  delete: createReadonlyMethod(\"delete\"),\n  clear: createReadonlyMethod(\"clear\"),\n  forEach: createForEach(true, false)\n};\nvar shallowReadonlyInstrumentations = {\n  get(key) {\n    return get$1(this, key, true, true);\n  },\n  get size() {\n    return size(this, true);\n  },\n  has(key) {\n    return has$1.call(this, key, true);\n  },\n  add: createReadonlyMethod(\"add\"),\n  set: createReadonlyMethod(\"set\"),\n  delete: createReadonlyMethod(\"delete\"),\n  clear: createReadonlyMethod(\"clear\"),\n  forEach: createForEach(true, true)\n};\nvar iteratorMethods = [\"keys\", \"values\", \"entries\", Symbol.iterator];\niteratorMethods.forEach((method) => {\n  mutableInstrumentations[method] = createIterableMethod(method, false, false);\n  readonlyInstrumentations[method] = createIterableMethod(method, true, false);\n  shallowInstrumentations[method] = createIterableMethod(method, false, true);\n  shallowReadonlyInstrumentations[method] = createIterableMethod(method, true, true);\n});\nfunction createInstrumentationGetter(isReadonly, shallow) {\n  const instrumentations = shallow ? isReadonly ? shallowReadonlyInstrumentations : shallowInstrumentations : isReadonly ? readonlyInstrumentations : mutableInstrumentations;\n  return (target, key, receiver) => {\n    if (key === \"__v_isReactive\") {\n      return !isReadonly;\n    } else if (key === \"__v_isReadonly\") {\n      return isReadonly;\n    } else if (key === \"__v_raw\") {\n      return target;\n    }\n    return Reflect.get(hasOwn(instrumentations, key) && key in target ? instrumentations : target, key, receiver);\n  };\n}\nvar mutableCollectionHandlers = {\n  get: createInstrumentationGetter(false, false)\n};\nvar shallowCollectionHandlers = {\n  get: createInstrumentationGetter(false, true)\n};\nvar readonlyCollectionHandlers = {\n  get: createInstrumentationGetter(true, false)\n};\nvar shallowReadonlyCollectionHandlers = {\n  get: createInstrumentationGetter(true, true)\n};\nfunction checkIdentityKeys(target, has2, key) {\n  const rawKey = toRaw(key);\n  if (rawKey !== key && has2.call(target, rawKey)) {\n    const type = toRawType(target);\n    console.warn(`Reactive ${type} contains both the raw and reactive versions of the same object${type === `Map` ? ` as keys` : ``}, which can lead to inconsistencies. Avoid differentiating between the raw and reactive versions of an object and only use the reactive version if possible.`);\n  }\n}\nvar reactiveMap = new WeakMap();\nvar shallowReactiveMap = new WeakMap();\nvar readonlyMap = new WeakMap();\nvar shallowReadonlyMap = new WeakMap();\nfunction targetTypeMap(rawType) {\n  switch (rawType) {\n    case \"Object\":\n    case \"Array\":\n      return 1;\n    case \"Map\":\n    case \"Set\":\n    case \"WeakMap\":\n    case \"WeakSet\":\n      return 2;\n    default:\n      return 0;\n  }\n}\nfunction getTargetType(value) {\n  return value[\"__v_skip\"] || !Object.isExtensible(value) ? 0 : targetTypeMap(toRawType(value));\n}\nfunction reactive2(target) {\n  if (target && target[\"__v_isReadonly\"]) {\n    return target;\n  }\n  return createReactiveObject(target, false, mutableHandlers, mutableCollectionHandlers, reactiveMap);\n}\nfunction readonly(target) {\n  return createReactiveObject(target, true, readonlyHandlers, readonlyCollectionHandlers, readonlyMap);\n}\nfunction createReactiveObject(target, isReadonly, baseHandlers, collectionHandlers, proxyMap) {\n  if (!isObject(target)) {\n    if (true) {\n      console.warn(`value cannot be made reactive: ${String(target)}`);\n    }\n    return target;\n  }\n  if (target[\"__v_raw\"] && !(isReadonly && target[\"__v_isReactive\"])) {\n    return target;\n  }\n  const existingProxy = proxyMap.get(target);\n  if (existingProxy) {\n    return existingProxy;\n  }\n  const targetType = getTargetType(target);\n  if (targetType === 0) {\n    return target;\n  }\n  const proxy = new Proxy(target, targetType === 2 ? collectionHandlers : baseHandlers);\n  proxyMap.set(target, proxy);\n  return proxy;\n}\nfunction toRaw(observed) {\n  return observed && toRaw(observed[\"__v_raw\"]) || observed;\n}\nfunction isRef(r) {\n  return Boolean(r && r.__v_isRef === true);\n}\n\n// packages/alpinejs/src/magics/$nextTick.js\nmagic(\"nextTick\", () => nextTick);\n\n// packages/alpinejs/src/magics/$dispatch.js\nmagic(\"dispatch\", (el) => dispatch.bind(dispatch, el));\n\n// packages/alpinejs/src/magics/$watch.js\nmagic(\"watch\", (el, {evaluateLater: evaluateLater2, effect: effect3}) => (key, callback) => {\n  let evaluate2 = evaluateLater2(key);\n  let firstTime = true;\n  let oldValue;\n  let effectReference = effect3(() => evaluate2((value) => {\n    JSON.stringify(value);\n    if (!firstTime) {\n      queueMicrotask(() => {\n        callback(value, oldValue);\n        oldValue = value;\n      });\n    } else {\n      oldValue = value;\n    }\n    firstTime = false;\n  }));\n  el._x_effects.delete(effectReference);\n});\n\n// packages/alpinejs/src/magics/$store.js\nmagic(\"store\", getStores);\n\n// packages/alpinejs/src/magics/$data.js\nmagic(\"data\", (el) => scope(el));\n\n// packages/alpinejs/src/magics/$root.js\nmagic(\"root\", (el) => closestRoot(el));\n\n// packages/alpinejs/src/magics/$refs.js\nmagic(\"refs\", (el) => {\n  if (el._x_refs_proxy)\n    return el._x_refs_proxy;\n  el._x_refs_proxy = mergeProxies(getArrayOfRefObject(el));\n  return el._x_refs_proxy;\n});\nfunction getArrayOfRefObject(el) {\n  let refObjects = [];\n  let currentEl = el;\n  while (currentEl) {\n    if (currentEl._x_refs)\n      refObjects.push(currentEl._x_refs);\n    currentEl = currentEl.parentNode;\n  }\n  return refObjects;\n}\n\n// packages/alpinejs/src/ids.js\nvar globalIdMemo = {};\nfunction findAndIncrementId(name) {\n  if (!globalIdMemo[name])\n    globalIdMemo[name] = 0;\n  return ++globalIdMemo[name];\n}\nfunction closestIdRoot(el, name) {\n  return findClosest(el, (element) => {\n    if (element._x_ids && element._x_ids[name])\n      return true;\n  });\n}\nfunction setIdRoot(el, name) {\n  if (!el._x_ids)\n    el._x_ids = {};\n  if (!el._x_ids[name])\n    el._x_ids[name] = findAndIncrementId(name);\n}\n\n// packages/alpinejs/src/magics/$id.js\nmagic(\"id\", (el) => (name, key = null) => {\n  let root = closestIdRoot(el, name);\n  let id = root ? root._x_ids[name] : findAndIncrementId(name);\n  return key ? `${name}-${id}-${key}` : `${name}-${id}`;\n});\n\n// packages/alpinejs/src/magics/$el.js\nmagic(\"el\", (el) => el);\n\n// packages/alpinejs/src/directives/x-modelable.js\ndirective(\"modelable\", (el, {expression}, {effect: effect3, evaluateLater: evaluateLater2}) => {\n  let func = evaluateLater2(expression);\n  let innerGet = () => {\n    let result;\n    func((i) => result = i);\n    return result;\n  };\n  let evaluateInnerSet = evaluateLater2(`${expression} = __placeholder`);\n  let innerSet = (val) => evaluateInnerSet(() => {\n  }, {scope: {__placeholder: val}});\n  let initialValue = innerGet();\n  innerSet(initialValue);\n  queueMicrotask(() => {\n    if (!el._x_model)\n      return;\n    el._x_removeModelListeners[\"default\"]();\n    let outerGet = el._x_model.get;\n    let outerSet = el._x_model.set;\n    effect3(() => innerSet(outerGet()));\n    effect3(() => outerSet(innerGet()));\n  });\n});\n\n// packages/alpinejs/src/directives/x-teleport.js\ndirective(\"teleport\", (el, {expression}, {cleanup: cleanup2}) => {\n  if (el.tagName.toLowerCase() !== \"template\")\n    warn(\"x-teleport can only be used on a <template> tag\", el);\n  let target = document.querySelector(expression);\n  if (!target)\n    warn(`Cannot find x-teleport element for selector: \"${expression}\"`);\n  let clone2 = el.content.cloneNode(true).firstElementChild;\n  el._x_teleport = clone2;\n  clone2._x_teleportBack = el;\n  if (el._x_forwardEvents) {\n    el._x_forwardEvents.forEach((eventName) => {\n      clone2.addEventListener(eventName, (e) => {\n        e.stopPropagation();\n        el.dispatchEvent(new e.constructor(e.type, e));\n      });\n    });\n  }\n  addScopeToNode(clone2, {}, el);\n  mutateDom(() => {\n    target.appendChild(clone2);\n    initTree(clone2);\n    clone2._x_ignore = true;\n  });\n  cleanup2(() => clone2.remove());\n});\n\n// packages/alpinejs/src/directives/x-ignore.js\nvar handler = () => {\n};\nhandler.inline = (el, {modifiers}, {cleanup: cleanup2}) => {\n  modifiers.includes(\"self\") ? el._x_ignoreSelf = true : el._x_ignore = true;\n  cleanup2(() => {\n    modifiers.includes(\"self\") ? delete el._x_ignoreSelf : delete el._x_ignore;\n  });\n};\ndirective(\"ignore\", handler);\n\n// packages/alpinejs/src/directives/x-effect.js\ndirective(\"effect\", (el, {expression}, {effect: effect3}) => effect3(evaluateLater(el, expression)));\n\n// packages/alpinejs/src/utils/on.js\nfunction on(el, event, modifiers, callback) {\n  let listenerTarget = el;\n  let handler3 = (e) => callback(e);\n  let options = {};\n  let wrapHandler = (callback2, wrapper) => (e) => wrapper(callback2, e);\n  if (modifiers.includes(\"dot\"))\n    event = dotSyntax(event);\n  if (modifiers.includes(\"camel\"))\n    event = camelCase2(event);\n  if (modifiers.includes(\"passive\"))\n    options.passive = true;\n  if (modifiers.includes(\"capture\"))\n    options.capture = true;\n  if (modifiers.includes(\"window\"))\n    listenerTarget = window;\n  if (modifiers.includes(\"document\"))\n    listenerTarget = document;\n  if (modifiers.includes(\"prevent\"))\n    handler3 = wrapHandler(handler3, (next, e) => {\n      e.preventDefault();\n      next(e);\n    });\n  if (modifiers.includes(\"stop\"))\n    handler3 = wrapHandler(handler3, (next, e) => {\n      e.stopPropagation();\n      next(e);\n    });\n  if (modifiers.includes(\"self\"))\n    handler3 = wrapHandler(handler3, (next, e) => {\n      e.target === el && next(e);\n    });\n  if (modifiers.includes(\"away\") || modifiers.includes(\"outside\")) {\n    listenerTarget = document;\n    handler3 = wrapHandler(handler3, (next, e) => {\n      if (el.contains(e.target))\n        return;\n      if (e.target.isConnected === false)\n        return;\n      if (el.offsetWidth < 1 && el.offsetHeight < 1)\n        return;\n      if (el._x_isShown === false)\n        return;\n      next(e);\n    });\n  }\n  if (modifiers.includes(\"once\")) {\n    handler3 = wrapHandler(handler3, (next, e) => {\n      next(e);\n      listenerTarget.removeEventListener(event, handler3, options);\n    });\n  }\n  handler3 = wrapHandler(handler3, (next, e) => {\n    if (isKeyEvent(event)) {\n      if (isListeningForASpecificKeyThatHasntBeenPressed(e, modifiers)) {\n        return;\n      }\n    }\n    next(e);\n  });\n  if (modifiers.includes(\"debounce\")) {\n    let nextModifier = modifiers[modifiers.indexOf(\"debounce\") + 1] || \"invalid-wait\";\n    let wait = isNumeric(nextModifier.split(\"ms\")[0]) ? Number(nextModifier.split(\"ms\")[0]) : 250;\n    handler3 = debounce(handler3, wait);\n  }\n  if (modifiers.includes(\"throttle\")) {\n    let nextModifier = modifiers[modifiers.indexOf(\"throttle\") + 1] || \"invalid-wait\";\n    let wait = isNumeric(nextModifier.split(\"ms\")[0]) ? Number(nextModifier.split(\"ms\")[0]) : 250;\n    handler3 = throttle(handler3, wait);\n  }\n  listenerTarget.addEventListener(event, handler3, options);\n  return () => {\n    listenerTarget.removeEventListener(event, handler3, options);\n  };\n}\nfunction dotSyntax(subject) {\n  return subject.replace(/-/g, \".\");\n}\nfunction camelCase2(subject) {\n  return subject.toLowerCase().replace(/-(\\w)/g, (match, char) => char.toUpperCase());\n}\nfunction isNumeric(subject) {\n  return !Array.isArray(subject) && !isNaN(subject);\n}\nfunction kebabCase2(subject) {\n  return subject.replace(/([a-z])([A-Z])/g, \"$1-$2\").replace(/[_\\s]/, \"-\").toLowerCase();\n}\nfunction isKeyEvent(event) {\n  return [\"keydown\", \"keyup\"].includes(event);\n}\nfunction isListeningForASpecificKeyThatHasntBeenPressed(e, modifiers) {\n  let keyModifiers = modifiers.filter((i) => {\n    return ![\"window\", \"document\", \"prevent\", \"stop\", \"once\"].includes(i);\n  });\n  if (keyModifiers.includes(\"debounce\")) {\n    let debounceIndex = keyModifiers.indexOf(\"debounce\");\n    keyModifiers.splice(debounceIndex, isNumeric((keyModifiers[debounceIndex + 1] || \"invalid-wait\").split(\"ms\")[0]) ? 2 : 1);\n  }\n  if (keyModifiers.length === 0)\n    return false;\n  if (keyModifiers.length === 1 && keyToModifiers(e.key).includes(keyModifiers[0]))\n    return false;\n  const systemKeyModifiers = [\"ctrl\", \"shift\", \"alt\", \"meta\", \"cmd\", \"super\"];\n  const selectedSystemKeyModifiers = systemKeyModifiers.filter((modifier) => keyModifiers.includes(modifier));\n  keyModifiers = keyModifiers.filter((i) => !selectedSystemKeyModifiers.includes(i));\n  if (selectedSystemKeyModifiers.length > 0) {\n    const activelyPressedKeyModifiers = selectedSystemKeyModifiers.filter((modifier) => {\n      if (modifier === \"cmd\" || modifier === \"super\")\n        modifier = \"meta\";\n      return e[`${modifier}Key`];\n    });\n    if (activelyPressedKeyModifiers.length === selectedSystemKeyModifiers.length) {\n      if (keyToModifiers(e.key).includes(keyModifiers[0]))\n        return false;\n    }\n  }\n  return true;\n}\nfunction keyToModifiers(key) {\n  if (!key)\n    return [];\n  key = kebabCase2(key);\n  let modifierToKeyMap = {\n    ctrl: \"control\",\n    slash: \"/\",\n    space: \"-\",\n    spacebar: \"-\",\n    cmd: \"meta\",\n    esc: \"escape\",\n    up: \"arrow-up\",\n    down: \"arrow-down\",\n    left: \"arrow-left\",\n    right: \"arrow-right\",\n    period: \".\",\n    equal: \"=\"\n  };\n  modifierToKeyMap[key] = key;\n  return Object.keys(modifierToKeyMap).map((modifier) => {\n    if (modifierToKeyMap[modifier] === key)\n      return modifier;\n  }).filter((modifier) => modifier);\n}\n\n// packages/alpinejs/src/directives/x-model.js\ndirective(\"model\", (el, {modifiers, expression}, {effect: effect3, cleanup: cleanup2}) => {\n  let evaluate2 = evaluateLater(el, expression);\n  let assignmentExpression = `${expression} = rightSideOfExpression($event, ${expression})`;\n  let evaluateAssignment = evaluateLater(el, assignmentExpression);\n  var event = el.tagName.toLowerCase() === \"select\" || [\"checkbox\", \"radio\"].includes(el.type) || modifiers.includes(\"lazy\") ? \"change\" : \"input\";\n  let assigmentFunction = generateAssignmentFunction(el, modifiers, expression);\n  let removeListener = on(el, event, modifiers, (e) => {\n    evaluateAssignment(() => {\n    }, {scope: {\n      $event: e,\n      rightSideOfExpression: assigmentFunction\n    }});\n  });\n  if (!el._x_removeModelListeners)\n    el._x_removeModelListeners = {};\n  el._x_removeModelListeners[\"default\"] = removeListener;\n  cleanup2(() => el._x_removeModelListeners[\"default\"]());\n  let evaluateSetModel = evaluateLater(el, `${expression} = __placeholder`);\n  el._x_model = {\n    get() {\n      let result;\n      evaluate2((value) => result = value);\n      return result;\n    },\n    set(value) {\n      evaluateSetModel(() => {\n      }, {scope: {__placeholder: value}});\n    }\n  };\n  el._x_forceModelUpdate = () => {\n    evaluate2((value) => {\n      if (value === void 0 && expression.match(/\\./))\n        value = \"\";\n      window.fromModel = true;\n      mutateDom(() => bind(el, \"value\", value));\n      delete window.fromModel;\n    });\n  };\n  effect3(() => {\n    if (modifiers.includes(\"unintrusive\") && document.activeElement.isSameNode(el))\n      return;\n    el._x_forceModelUpdate();\n  });\n});\nfunction generateAssignmentFunction(el, modifiers, expression) {\n  if (el.type === \"radio\") {\n    mutateDom(() => {\n      if (!el.hasAttribute(\"name\"))\n        el.setAttribute(\"name\", expression);\n    });\n  }\n  return (event, currentValue) => {\n    return mutateDom(() => {\n      if (event instanceof CustomEvent && event.detail !== void 0) {\n        return event.detail || event.target.value;\n      } else if (el.type === \"checkbox\") {\n        if (Array.isArray(currentValue)) {\n          let newValue = modifiers.includes(\"number\") ? safeParseNumber(event.target.value) : event.target.value;\n          return event.target.checked ? currentValue.concat([newValue]) : currentValue.filter((el2) => !checkedAttrLooseCompare2(el2, newValue));\n        } else {\n          return event.target.checked;\n        }\n      } else if (el.tagName.toLowerCase() === \"select\" && el.multiple) {\n        return modifiers.includes(\"number\") ? Array.from(event.target.selectedOptions).map((option) => {\n          let rawValue = option.value || option.text;\n          return safeParseNumber(rawValue);\n        }) : Array.from(event.target.selectedOptions).map((option) => {\n          return option.value || option.text;\n        });\n      } else {\n        let rawValue = event.target.value;\n        return modifiers.includes(\"number\") ? safeParseNumber(rawValue) : modifiers.includes(\"trim\") ? rawValue.trim() : rawValue;\n      }\n    });\n  };\n}\nfunction safeParseNumber(rawValue) {\n  let number = rawValue ? parseFloat(rawValue) : null;\n  return isNumeric2(number) ? number : rawValue;\n}\nfunction checkedAttrLooseCompare2(valueA, valueB) {\n  return valueA == valueB;\n}\nfunction isNumeric2(subject) {\n  return !Array.isArray(subject) && !isNaN(subject);\n}\n\n// packages/alpinejs/src/directives/x-cloak.js\ndirective(\"cloak\", (el) => queueMicrotask(() => mutateDom(() => el.removeAttribute(prefix(\"cloak\")))));\n\n// packages/alpinejs/src/directives/x-init.js\naddInitSelector(() => `[${prefix(\"init\")}]`);\ndirective(\"init\", skipDuringClone((el, {expression}, {evaluate: evaluate2}) => {\n  if (typeof expression === \"string\") {\n    return !!expression.trim() && evaluate2(expression, {}, false);\n  }\n  return evaluate2(expression, {}, false);\n}));\n\n// packages/alpinejs/src/directives/x-text.js\ndirective(\"text\", (el, {expression}, {effect: effect3, evaluateLater: evaluateLater2}) => {\n  let evaluate2 = evaluateLater2(expression);\n  effect3(() => {\n    evaluate2((value) => {\n      mutateDom(() => {\n        el.textContent = value;\n      });\n    });\n  });\n});\n\n// packages/alpinejs/src/directives/x-html.js\ndirective(\"html\", (el, {expression}, {effect: effect3, evaluateLater: evaluateLater2}) => {\n  let evaluate2 = evaluateLater2(expression);\n  effect3(() => {\n    evaluate2((value) => {\n      mutateDom(() => {\n        el.innerHTML = value;\n        el._x_ignoreSelf = true;\n        initTree(el);\n        delete el._x_ignoreSelf;\n      });\n    });\n  });\n});\n\n// packages/alpinejs/src/directives/x-bind.js\nmapAttributes(startingWith(\":\", into(prefix(\"bind:\"))));\ndirective(\"bind\", (el, {value, modifiers, expression, original}, {effect: effect3}) => {\n  if (!value) {\n    return applyBindingsObject(el, expression, original, effect3);\n  }\n  if (value === \"key\")\n    return storeKeyForXFor(el, expression);\n  let evaluate2 = evaluateLater(el, expression);\n  effect3(() => evaluate2((result) => {\n    if (result === void 0 && expression.match(/\\./))\n      result = \"\";\n    mutateDom(() => bind(el, value, result, modifiers));\n  }));\n});\nfunction applyBindingsObject(el, expression, original, effect3) {\n  let bindingProviders = {};\n  injectBindingProviders(bindingProviders);\n  let getBindings = evaluateLater(el, expression);\n  let cleanupRunners = [];\n  while (cleanupRunners.length)\n    cleanupRunners.pop()();\n  getBindings((bindings) => {\n    let attributes = Object.entries(bindings).map(([name, value]) => ({name, value}));\n    let staticAttributes = attributesOnly(attributes);\n    attributes = attributes.map((attribute) => {\n      if (staticAttributes.find((attr) => attr.name === attribute.name)) {\n        return {\n          name: `x-bind:${attribute.name}`,\n          value: `\"${attribute.value}\"`\n        };\n      }\n      return attribute;\n    });\n    directives(el, attributes, original).map((handle) => {\n      cleanupRunners.push(handle.runCleanups);\n      handle();\n    });\n  }, {scope: bindingProviders});\n}\nfunction storeKeyForXFor(el, expression) {\n  el._x_keyExpression = expression;\n}\n\n// packages/alpinejs/src/directives/x-data.js\naddRootSelector(() => `[${prefix(\"data\")}]`);\ndirective(\"data\", skipDuringClone((el, {expression}, {cleanup: cleanup2}) => {\n  expression = expression === \"\" ? \"{}\" : expression;\n  let magicContext = {};\n  injectMagics(magicContext, el);\n  let dataProviderContext = {};\n  injectDataProviders(dataProviderContext, magicContext);\n  let data2 = evaluate(el, expression, {scope: dataProviderContext});\n  if (data2 === void 0)\n    data2 = {};\n  injectMagics(data2, el);\n  let reactiveData = reactive(data2);\n  initInterceptors(reactiveData);\n  let undo = addScopeToNode(el, reactiveData);\n  reactiveData[\"init\"] && evaluate(el, reactiveData[\"init\"]);\n  cleanup2(() => {\n    reactiveData[\"destroy\"] && evaluate(el, reactiveData[\"destroy\"]);\n    undo();\n  });\n}));\n\n// packages/alpinejs/src/directives/x-show.js\ndirective(\"show\", (el, {modifiers, expression}, {effect: effect3}) => {\n  let evaluate2 = evaluateLater(el, expression);\n  let hide = () => mutateDom(() => {\n    el.style.display = \"none\";\n    el._x_isShown = false;\n  });\n  let show = () => mutateDom(() => {\n    if (el.style.length === 1 && el.style.display === \"none\") {\n      el.removeAttribute(\"style\");\n    } else {\n      el.style.removeProperty(\"display\");\n    }\n    el._x_isShown = true;\n  });\n  let clickAwayCompatibleShow = () => setTimeout(show);\n  let toggle = once((value) => value ? show() : hide(), (value) => {\n    if (typeof el._x_toggleAndCascadeWithTransitions === \"function\") {\n      el._x_toggleAndCascadeWithTransitions(el, value, show, hide);\n    } else {\n      value ? clickAwayCompatibleShow() : hide();\n    }\n  });\n  let oldValue;\n  let firstTime = true;\n  effect3(() => evaluate2((value) => {\n    if (!firstTime && value === oldValue)\n      return;\n    if (modifiers.includes(\"immediate\"))\n      value ? clickAwayCompatibleShow() : hide();\n    toggle(value);\n    oldValue = value;\n    firstTime = false;\n  }));\n});\n\n// packages/alpinejs/src/directives/x-for.js\ndirective(\"for\", (el, {expression}, {effect: effect3, cleanup: cleanup2}) => {\n  let iteratorNames = parseForExpression(expression);\n  let evaluateItems = evaluateLater(el, iteratorNames.items);\n  let evaluateKey = evaluateLater(el, el._x_keyExpression || \"index\");\n  el._x_prevKeys = [];\n  el._x_lookup = {};\n  effect3(() => loop(el, iteratorNames, evaluateItems, evaluateKey));\n  cleanup2(() => {\n    Object.values(el._x_lookup).forEach((el2) => el2.remove());\n    delete el._x_prevKeys;\n    delete el._x_lookup;\n  });\n});\nfunction loop(el, iteratorNames, evaluateItems, evaluateKey) {\n  let isObject2 = (i) => typeof i === \"object\" && !Array.isArray(i);\n  let templateEl = el;\n  evaluateItems((items) => {\n    if (isNumeric3(items) && items >= 0) {\n      items = Array.from(Array(items).keys(), (i) => i + 1);\n    }\n    if (items === void 0)\n      items = [];\n    let lookup = el._x_lookup;\n    let prevKeys = el._x_prevKeys;\n    let scopes = [];\n    let keys = [];\n    if (isObject2(items)) {\n      items = Object.entries(items).map(([key, value]) => {\n        let scope2 = getIterationScopeVariables(iteratorNames, value, key, items);\n        evaluateKey((value2) => keys.push(value2), {scope: {index: key, ...scope2}});\n        scopes.push(scope2);\n      });\n    } else {\n      for (let i = 0; i < items.length; i++) {\n        let scope2 = getIterationScopeVariables(iteratorNames, items[i], i, items);\n        evaluateKey((value) => keys.push(value), {scope: {index: i, ...scope2}});\n        scopes.push(scope2);\n      }\n    }\n    let adds = [];\n    let moves = [];\n    let removes = [];\n    let sames = [];\n    for (let i = 0; i < prevKeys.length; i++) {\n      let key = prevKeys[i];\n      if (keys.indexOf(key) === -1)\n        removes.push(key);\n    }\n    prevKeys = prevKeys.filter((key) => !removes.includes(key));\n    let lastKey = \"template\";\n    for (let i = 0; i < keys.length; i++) {\n      let key = keys[i];\n      let prevIndex = prevKeys.indexOf(key);\n      if (prevIndex === -1) {\n        prevKeys.splice(i, 0, key);\n        adds.push([lastKey, i]);\n      } else if (prevIndex !== i) {\n        let keyInSpot = prevKeys.splice(i, 1)[0];\n        let keyForSpot = prevKeys.splice(prevIndex - 1, 1)[0];\n        prevKeys.splice(i, 0, keyForSpot);\n        prevKeys.splice(prevIndex, 0, keyInSpot);\n        moves.push([keyInSpot, keyForSpot]);\n      } else {\n        sames.push(key);\n      }\n      lastKey = key;\n    }\n    for (let i = 0; i < removes.length; i++) {\n      let key = removes[i];\n      if (!!lookup[key]._x_effects) {\n        lookup[key]._x_effects.forEach(dequeueJob);\n      }\n      lookup[key].remove();\n      lookup[key] = null;\n      delete lookup[key];\n    }\n    for (let i = 0; i < moves.length; i++) {\n      let [keyInSpot, keyForSpot] = moves[i];\n      let elInSpot = lookup[keyInSpot];\n      let elForSpot = lookup[keyForSpot];\n      let marker = document.createElement(\"div\");\n      mutateDom(() => {\n        elForSpot.after(marker);\n        elInSpot.after(elForSpot);\n        elForSpot._x_currentIfEl && elForSpot.after(elForSpot._x_currentIfEl);\n        marker.before(elInSpot);\n        elInSpot._x_currentIfEl && elInSpot.after(elInSpot._x_currentIfEl);\n        marker.remove();\n      });\n      refreshScope(elForSpot, scopes[keys.indexOf(keyForSpot)]);\n    }\n    for (let i = 0; i < adds.length; i++) {\n      let [lastKey2, index] = adds[i];\n      let lastEl = lastKey2 === \"template\" ? templateEl : lookup[lastKey2];\n      if (lastEl._x_currentIfEl)\n        lastEl = lastEl._x_currentIfEl;\n      let scope2 = scopes[index];\n      let key = keys[index];\n      let clone2 = document.importNode(templateEl.content, true).firstElementChild;\n      addScopeToNode(clone2, reactive(scope2), templateEl);\n      mutateDom(() => {\n        lastEl.after(clone2);\n        initTree(clone2);\n      });\n      if (typeof key === \"object\") {\n        warn(\"x-for key cannot be an object, it must be a string or an integer\", templateEl);\n      }\n      lookup[key] = clone2;\n    }\n    for (let i = 0; i < sames.length; i++) {\n      refreshScope(lookup[sames[i]], scopes[keys.indexOf(sames[i])]);\n    }\n    templateEl._x_prevKeys = keys;\n  });\n}\nfunction parseForExpression(expression) {\n  let forIteratorRE = /,([^,\\}\\]]*)(?:,([^,\\}\\]]*))?$/;\n  let stripParensRE = /^\\s*\\(|\\)\\s*$/g;\n  let forAliasRE = /([\\s\\S]*?)\\s+(?:in|of)\\s+([\\s\\S]*)/;\n  let inMatch = expression.match(forAliasRE);\n  if (!inMatch)\n    return;\n  let res = {};\n  res.items = inMatch[2].trim();\n  let item = inMatch[1].replace(stripParensRE, \"\").trim();\n  let iteratorMatch = item.match(forIteratorRE);\n  if (iteratorMatch) {\n    res.item = item.replace(forIteratorRE, \"\").trim();\n    res.index = iteratorMatch[1].trim();\n    if (iteratorMatch[2]) {\n      res.collection = iteratorMatch[2].trim();\n    }\n  } else {\n    res.item = item;\n  }\n  return res;\n}\nfunction getIterationScopeVariables(iteratorNames, item, index, items) {\n  let scopeVariables = {};\n  if (/^\\[.*\\]$/.test(iteratorNames.item) && Array.isArray(item)) {\n    let names = iteratorNames.item.replace(\"[\", \"\").replace(\"]\", \"\").split(\",\").map((i) => i.trim());\n    names.forEach((name, i) => {\n      scopeVariables[name] = item[i];\n    });\n  } else if (/^\\{.*\\}$/.test(iteratorNames.item) && !Array.isArray(item) && typeof item === \"object\") {\n    let names = iteratorNames.item.replace(\"{\", \"\").replace(\"}\", \"\").split(\",\").map((i) => i.trim());\n    names.forEach((name) => {\n      scopeVariables[name] = item[name];\n    });\n  } else {\n    scopeVariables[iteratorNames.item] = item;\n  }\n  if (iteratorNames.index)\n    scopeVariables[iteratorNames.index] = index;\n  if (iteratorNames.collection)\n    scopeVariables[iteratorNames.collection] = items;\n  return scopeVariables;\n}\nfunction isNumeric3(subject) {\n  return !Array.isArray(subject) && !isNaN(subject);\n}\n\n// packages/alpinejs/src/directives/x-ref.js\nfunction handler2() {\n}\nhandler2.inline = (el, {expression}, {cleanup: cleanup2}) => {\n  let root = closestRoot(el);\n  if (!root._x_refs)\n    root._x_refs = {};\n  root._x_refs[expression] = el;\n  cleanup2(() => delete root._x_refs[expression]);\n};\ndirective(\"ref\", handler2);\n\n// packages/alpinejs/src/directives/x-if.js\ndirective(\"if\", (el, {expression}, {effect: effect3, cleanup: cleanup2}) => {\n  let evaluate2 = evaluateLater(el, expression);\n  let show = () => {\n    if (el._x_currentIfEl)\n      return el._x_currentIfEl;\n    let clone2 = el.content.cloneNode(true).firstElementChild;\n    addScopeToNode(clone2, {}, el);\n    mutateDom(() => {\n      el.after(clone2);\n      initTree(clone2);\n    });\n    el._x_currentIfEl = clone2;\n    el._x_undoIf = () => {\n      walk(clone2, (node) => {\n        if (!!node._x_effects) {\n          node._x_effects.forEach(dequeueJob);\n        }\n      });\n      clone2.remove();\n      delete el._x_currentIfEl;\n    };\n    return clone2;\n  };\n  let hide = () => {\n    if (!el._x_undoIf)\n      return;\n    el._x_undoIf();\n    delete el._x_undoIf;\n  };\n  effect3(() => evaluate2((value) => {\n    value ? show() : hide();\n  }));\n  cleanup2(() => el._x_undoIf && el._x_undoIf());\n});\n\n// packages/alpinejs/src/directives/x-id.js\ndirective(\"id\", (el, {expression}, {evaluate: evaluate2}) => {\n  let names = evaluate2(expression);\n  names.forEach((name) => setIdRoot(el, name));\n});\n\n// packages/alpinejs/src/directives/x-on.js\nmapAttributes(startingWith(\"@\", into(prefix(\"on:\"))));\ndirective(\"on\", skipDuringClone((el, {value, modifiers, expression}, {cleanup: cleanup2}) => {\n  let evaluate2 = expression ? evaluateLater(el, expression) : () => {\n  };\n  if (el.tagName.toLowerCase() === \"template\") {\n    if (!el._x_forwardEvents)\n      el._x_forwardEvents = [];\n    if (!el._x_forwardEvents.includes(value))\n      el._x_forwardEvents.push(value);\n  }\n  let removeListener = on(el, value, modifiers, (e) => {\n    evaluate2(() => {\n    }, {scope: {$event: e}, params: [e]});\n  });\n  cleanup2(() => removeListener());\n}));\n\n// packages/alpinejs/src/index.js\nalpine_default.setEvaluator(normalEvaluator);\nalpine_default.setReactivityEngine({reactive: reactive2, effect: effect2, release: stop, raw: toRaw});\nvar src_default = alpine_default;\n\n// packages/alpinejs/builds/module.js\nvar module_default = src_default;\nexport {\n  module_default as default\n};\n", "export default function toInteger(dirtyNumber) {\n  if (dirtyNumber === null || dirtyNumber === true || dirtyNumber === false) {\n    return NaN;\n  }\n\n  var number = Number(dirtyNumber);\n\n  if (isNaN(number)) {\n    return number;\n  }\n\n  return number < 0 ? Math.ceil(number) : Math.floor(number);\n}", "export default function requiredArgs(required, args) {\n  if (args.length < required) {\n    throw new TypeError(required + ' argument' + (required > 1 ? 's' : '') + ' required, but only ' + args.length + ' present');\n  }\n}", "import requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name toDate\n * @category Common Helpers\n * @summary Convert the given argument to an instance of Date.\n *\n * @description\n * Convert the given argument to an instance of Date.\n *\n * If the argument is an instance of Date, the function returns its clone.\n *\n * If the argument is a number, it is treated as a timestamp.\n *\n * If the argument is none of the above, the function returns Invalid Date.\n *\n * **Note**: *all* Date arguments passed to any *date-fns* function is processed by `toDate`.\n *\n * @param {Date|Number} argument - the value to convert\n * @returns {Date} the parsed date in the local time zone\n * @throws {TypeError} 1 argument required\n *\n * @example\n * // Clone the date:\n * const result = toDate(new Date(2014, 1, 11, 11, 30, 30))\n * //=> Tue Feb 11 2014 11:30:30\n *\n * @example\n * // Convert the timestamp to date:\n * const result = toDate(1392098430000)\n * //=> Tue Feb 11 2014 11:30:30\n */\n\nexport default function toDate(argument) {\n  requiredArgs(1, arguments);\n  var argStr = Object.prototype.toString.call(argument); // Clone the date\n\n  if (argument instanceof Date || typeof argument === 'object' && argStr === '[object Date]') {\n    // Prevent the date to lose the milliseconds when passed to new Date() in IE10\n    return new Date(argument.getTime());\n  } else if (typeof argument === 'number' || argStr === '[object Number]') {\n    return new Date(argument);\n  } else {\n    if ((typeof argument === 'string' || argStr === '[object String]') && typeof console !== 'undefined') {\n      // eslint-disable-next-line no-console\n      console.warn(\"Starting with v2.0.0-beta.1 date-fns doesn't accept strings as date arguments. Please use `parseISO` to parse strings. See: https://git.io/fjule\"); // eslint-disable-next-line no-console\n\n      console.warn(new Error().stack);\n    }\n\n    return new Date(NaN);\n  }\n}", "import toInteger from \"../_lib/toInteger/index.js\";\nimport toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name addDays\n * @category Day Helpers\n * @summary Add the specified number of days to the given date.\n *\n * @description\n * Add the specified number of days to the given date.\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} date - the date to be changed\n * @param {Number} amount - the amount of days to be added. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.\n * @returns {Date} - the new date with the days added\n * @throws {TypeError} - 2 arguments required\n *\n * @example\n * // Add 10 days to 1 September 2014:\n * const result = addDays(new Date(2014, 8, 1), 10)\n * //=> Thu Sep 11 2014 00:00:00\n */\n\nexport default function addDays(dirtyDate, dirtyAmount) {\n  requiredArgs(2, arguments);\n  var date = toDate(dirtyDate);\n  var amount = toInteger(dirtyAmount);\n\n  if (isNaN(amount)) {\n    return new Date(NaN);\n  }\n\n  if (!amount) {\n    // If 0 days, no-op to avoid changing times in the hour before end of DST\n    return date;\n  }\n\n  date.setDate(date.getDate() + amount);\n  return date;\n}", "import toInteger from \"../_lib/toInteger/index.js\";\nimport toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name addMonths\n * @category Month Helpers\n * @summary Add the specified number of months to the given date.\n *\n * @description\n * Add the specified number of months to the given date.\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} date - the date to be changed\n * @param {Number} amount - the amount of months to be added. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.\n * @returns {Date} the new date with the months added\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // Add 5 months to 1 September 2014:\n * const result = addMonths(new Date(2014, 8, 1), 5)\n * //=> Sun Feb 01 2015 00:00:00\n */\n\nexport default function addMonths(dirtyDate, dirtyAmount) {\n  requiredArgs(2, arguments);\n  var date = toDate(dirtyDate);\n  var amount = toInteger(dirtyAmount);\n\n  if (isNaN(amount)) {\n    return new Date(NaN);\n  }\n\n  if (!amount) {\n    // If 0 months, no-op to avoid changing times in the hour before end of DST\n    return date;\n  }\n\n  var dayOfMonth = date.getDate(); // The JS Date object supports date math by accepting out-of-bounds values for\n  // month, day, etc. For example, new Date(2020, 0, 0) returns 31 Dec 2019 and\n  // new Date(2020, 13, 1) returns 1 Feb 2021.  This is *almost* the behavior we\n  // want except that dates will wrap around the end of a month, meaning that\n  // new Date(2020, 13, 31) will return 3 Mar 2021 not 28 Feb 2021 as desired. So\n  // we'll default to the end of the desired month by adding 1 to the desired\n  // month and using a date of 0 to back up one day to the end of the desired\n  // month.\n\n  var endOfDesiredMonth = new Date(date.getTime());\n  endOfDesiredMonth.setMonth(date.getMonth() + amount + 1, 0);\n  var daysInMonth = endOfDesiredMonth.getDate();\n\n  if (dayOfMonth >= daysInMonth) {\n    // If we're already at the end of the month, then this is the correct date\n    // and we're done.\n    return endOfDesiredMonth;\n  } else {\n    // Otherwise, we now know that setting the original day-of-month value won't\n    // cause an overflow, so set the desired day-of-month. Note that we can't\n    // just set the date of `endOfDesiredMonth` because that object may have had\n    // its time changed in the unusual case where where a DST transition was on\n    // the last day of the month and its local time was in the hour skipped or\n    // repeated next to a DST transition.  So we use `date` instead which is\n    // guaranteed to still have the original time.\n    date.setFullYear(endOfDesiredMonth.getFullYear(), endOfDesiredMonth.getMonth(), dayOfMonth);\n    return date;\n  }\n}", "import addDays from \"../addDays/index.js\";\nimport addMonths from \"../addMonths/index.js\";\nimport toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\nimport toInteger from \"../_lib/toInteger/index.js\";\n\n/**\n * @name add\n * @category Common Helpers\n * @summary Add the specified years, months, weeks, days, hours, minutes and seconds to the given date.\n *\n * @description\n * Add the specified years, months, weeks, days, hours, minutes and seconds to the given date.\n *\n * @param {Date|Number} date - the date to be changed\n * @param {Duration} duration - the object with years, months, weeks, days, hours, minutes and seconds to be added. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.\n *\n * | Key            | Description                        |\n * |----------------|------------------------------------|\n * | years          | Amount of years to be added        |\n * | months         | Amount of months to be added       |\n * | weeks          | Amount of weeks to be added        |\n * | days           | Amount of days to be added         |\n * | hours          | Amount of hours to be added        |\n * | minutes        | Amount of minutes to be added      |\n * | seconds        | Amount of seconds to be added      |\n *\n * All values default to 0\n *\n * @returns {Date} the new date with the seconds added\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // Add the following duration to 1 September 2014, 10:19:50\n * const result = add(new Date(2014, 8, 1, 10, 19, 50), {\n *   years: 2,\n *   months: 9,\n *   weeks: 1,\n *   days: 7,\n *   hours: 5,\n *   minutes: 9,\n *   seconds: 30,\n * })\n * //=> Thu Jun 15 2017 15:29:20\n */\nexport default function add(dirtyDate, duration) {\n  requiredArgs(2, arguments);\n  if (!duration || typeof duration !== 'object') return new Date(NaN);\n  var years = duration.years ? toInteger(duration.years) : 0;\n  var months = duration.months ? toInteger(duration.months) : 0;\n  var weeks = duration.weeks ? toInteger(duration.weeks) : 0;\n  var days = duration.days ? toInteger(duration.days) : 0;\n  var hours = duration.hours ? toInteger(duration.hours) : 0;\n  var minutes = duration.minutes ? toInteger(duration.minutes) : 0;\n  var seconds = duration.seconds ? toInteger(duration.seconds) : 0; // Add years and months\n\n  var date = toDate(dirtyDate);\n  var dateWithMonths = months || years ? addMonths(date, months + years * 12) : date; // Add weeks and days\n\n  var dateWithDays = days || weeks ? addDays(dateWithMonths, days + weeks * 7) : dateWithMonths; // Add days, hours, minutes and seconds\n\n  var minutesToAdd = minutes + hours * 60;\n  var secondsToAdd = seconds + minutesToAdd * 60;\n  var msToAdd = secondsToAdd * 1000;\n  var finalDate = new Date(dateWithDays.getTime() + msToAdd);\n  return finalDate;\n}", "import toInteger from \"../_lib/toInteger/index.js\";\nimport toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name addMilliseconds\n * @category Millisecond Helpers\n * @summary Add the specified number of milliseconds to the given date.\n *\n * @description\n * Add the specified number of milliseconds to the given date.\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} date - the date to be changed\n * @param {Number} amount - the amount of milliseconds to be added. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.\n * @returns {Date} the new date with the milliseconds added\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // Add 750 milliseconds to 10 July 2014 12:45:30.000:\n * const result = addMilliseconds(new Date(2014, 6, 10, 12, 45, 30, 0), 750)\n * //=> Thu Jul 10 2014 12:45:30.750\n */\n\nexport default function addMilliseconds(dirtyDate, dirtyAmount) {\n  requiredArgs(2, arguments);\n  var timestamp = toDate(dirtyDate).getTime();\n  var amount = toInteger(dirtyAmount);\n  return new Date(timestamp + amount);\n}", "/**\n * Google Chrome as of 67.0.3396.87 introduced timezones with offset that includes seconds.\n * They usually appear for dates that denote time before the timezones were introduced\n * (e.g. for 'Europe/Prague' timezone the offset is GMT+00:57:44 before 1 October 1891\n * and GMT+01:00:00 after that date)\n *\n * Date#getTimezoneOffset returns the offset in minutes and would return 57 for the example above,\n * which would lead to incorrect calculations.\n *\n * This function returns the timezone offset in milliseconds that takes seconds in account.\n */\nexport default function getTimezoneOffsetInMilliseconds(date) {\n  var utcDate = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds()));\n  utcDate.setUTCFullYear(date.getFullYear());\n  return date.getTime() - utcDate.getTime();\n}", "import toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name startOfDay\n * @category Day Helpers\n * @summary Return the start of a day for the given date.\n *\n * @description\n * Return the start of a day for the given date.\n * The result will be in the local timezone.\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} date - the original date\n * @returns {Date} the start of a day\n * @throws {TypeError} 1 argument required\n *\n * @example\n * // The start of a day for 2 September 2014 11:55:00:\n * const result = startOfDay(new Date(2014, 8, 2, 11, 55, 0))\n * //=> Tue Sep 02 2014 00:00:00\n */\n\nexport default function startOfDay(dirtyDate) {\n  requiredArgs(1, arguments);\n  var date = toDate(dirtyDate);\n  date.setHours(0, 0, 0, 0);\n  return date;\n}", "import getTimezoneOffsetInMilliseconds from \"../_lib/getTimezoneOffsetInMilliseconds/index.js\";\nimport startOfDay from \"../startOfDay/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\nvar MILLISECONDS_IN_DAY = 86400000;\n/**\n * @name differenceInCalendarDays\n * @category Day Helpers\n * @summary Get the number of calendar days between the given dates.\n *\n * @description\n * Get the number of calendar days between the given dates. This means that the times are removed\n * from the dates and then the difference in days is calculated.\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} dateLeft - the later date\n * @param {Date|Number} dateRight - the earlier date\n * @returns {Number} the number of calendar days\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // How many calendar days are between\n * // 2 July 2011 23:00:00 and 2 July 2012 00:00:00?\n * const result = differenceInCalendarDays(\n *   new Date(2012, 6, 2, 0, 0),\n *   new Date(2011, 6, 2, 23, 0)\n * )\n * //=> 366\n * // How many calendar days are between\n * // 2 July 2011 23:59:00 and 3 July 2011 00:01:00?\n * const result = differenceInCalendarDays(\n *   new Date(2011, 6, 3, 0, 1),\n *   new Date(2011, 6, 2, 23, 59)\n * )\n * //=> 1\n */\n\nexport default function differenceInCalendarDays(dirtyDateLeft, dirtyDateRight) {\n  requiredArgs(2, arguments);\n  var startOfDayLeft = startOfDay(dirtyDateLeft);\n  var startOfDayRight = startOfDay(dirtyDateRight);\n  var timestampLeft = startOfDayLeft.getTime() - getTimezoneOffsetInMilliseconds(startOfDayLeft);\n  var timestampRight = startOfDayRight.getTime() - getTimezoneOffsetInMilliseconds(startOfDayRight); // Round the number of days to the nearest integer\n  // because the number of milliseconds in a day is not constant\n  // (e.g. it's different in the day of the daylight saving time clock shift)\n\n  return Math.round((timestampLeft - timestampRight) / MILLISECONDS_IN_DAY);\n}", "import toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name isValid\n * @category Common Helpers\n * @summary Is the given date valid?\n *\n * @description\n * Returns false if argument is Invalid Date and true otherwise.\n * Argument is converted to Date using `toDate`. See [toDate]{@link https://date-fns.org/docs/toDate}\n * Invalid Date is a Date, whose time value is NaN.\n *\n * Time value of Date: http://es5.github.io/#x15.9.1.1\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * - Now `isValid` doesn't throw an exception\n *   if the first argument is not an instance of Date.\n *   Instead, argument is converted beforehand using `toDate`.\n *\n *   Examples:\n *\n *   | `isValid` argument        | Before v2.0.0 | v2.0.0 onward |\n *   |---------------------------|---------------|---------------|\n *   | `new Date()`              | `true`        | `true`        |\n *   | `new Date('2016-01-01')`  | `true`        | `true`        |\n *   | `new Date('')`            | `false`       | `false`       |\n *   | `new Date(1488370835081)` | `true`        | `true`        |\n *   | `new Date(NaN)`           | `false`       | `false`       |\n *   | `'2016-01-01'`            | `TypeError`   | `false`       |\n *   | `''`                      | `TypeError`   | `false`       |\n *   | `1488370835081`           | `TypeError`   | `true`        |\n *   | `NaN`                     | `TypeError`   | `false`       |\n *\n *   We introduce this change to make *date-fns* consistent with ECMAScript behavior\n *   that try to coerce arguments to the expected type\n *   (which is also the case with other *date-fns* functions).\n *\n * @param {*} date - the date to check\n * @returns {Boolean} the date is valid\n * @throws {TypeError} 1 argument required\n *\n * @example\n * // For the valid date:\n * var result = isValid(new Date(2014, 1, 31))\n * //=> true\n *\n * @example\n * // For the value, convertable into a date:\n * var result = isValid(1393804800000)\n * //=> true\n *\n * @example\n * // For the invalid date:\n * var result = isValid(new Date(''))\n * //=> false\n */\n\nexport default function isValid(dirtyDate) {\n  requiredArgs(1, arguments);\n  var date = toDate(dirtyDate);\n  return !isNaN(date);\n}", "import toDate from \"../toDate/index.js\";\nimport differenceInCalendarDays from \"../differenceInCalendarDays/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\"; // Like `compareAsc` but uses local time not UTC, which is needed\n// for accurate equality comparisons of UTC timestamps that end up\n// having the same representation in local time, e.g. one hour before\n// DST ends vs. the instant that DST ends.\n\nfunction compareLocalAsc(dateLeft, dateRight) {\n  var diff = dateLeft.getFullYear() - dateRight.getFullYear() || dateLeft.getMonth() - dateRight.getMonth() || dateLeft.getDate() - dateRight.getDate() || dateLeft.getHours() - dateRight.getHours() || dateLeft.getMinutes() - dateRight.getMinutes() || dateLeft.getSeconds() - dateRight.getSeconds() || dateLeft.getMilliseconds() - dateRight.getMilliseconds();\n\n  if (diff < 0) {\n    return -1;\n  } else if (diff > 0) {\n    return 1; // Return 0 if diff is 0; return NaN if diff is NaN\n  } else {\n    return diff;\n  }\n}\n/**\n * @name differenceInDays\n * @category Day Helpers\n * @summary Get the number of full days between the given dates.\n *\n * @description\n * Get the number of full day periods between two dates. Fractional days are\n * truncated towards zero.\n *\n * One \"full day\" is the distance between a local time in one day to the same\n * local time on the next or previous day. A full day can sometimes be less than\n * or more than 24 hours if a daylight savings change happens between two dates.\n *\n * To ignore DST and only measure exact 24-hour periods, use this instead:\n * `Math.floor(differenceInHours(dateLeft, dateRight)/24)|0`.\n *\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} dateLeft - the later date\n * @param {Date|Number} dateRight - the earlier date\n * @returns {Number} the number of full days according to the local timezone\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // How many full days are between\n * // 2 July 2011 23:00:00 and 2 July 2012 00:00:00?\n * const result = differenceInDays(\n *   new Date(2012, 6, 2, 0, 0),\n *   new Date(2011, 6, 2, 23, 0)\n * )\n * //=> 365\n * // How many full days are between\n * // 2 July 2011 23:59:00 and 3 July 2011 00:01:00?\n * const result = differenceInDays(\n *   new Date(2011, 6, 3, 0, 1),\n *   new Date(2011, 6, 2, 23, 59)\n * )\n * //=> 0\n * // How many full days are between\n * // 1 March 2020 0:00 and 1 June 2020 0:00 ?\n * // Note: because local time is used, the\n * // result will always be 92 days, even in\n * // time zones where DST starts and the\n * // period has only 92*24-1 hours.\n * const result = differenceInDays(\n *   new Date(2020, 5, 1),\n *   new Date(2020, 2, 1)\n * )\n//=> 92\n */\n\n\nexport default function differenceInDays(dirtyDateLeft, dirtyDateRight) {\n  requiredArgs(2, arguments);\n  var dateLeft = toDate(dirtyDateLeft);\n  var dateRight = toDate(dirtyDateRight);\n  var sign = compareLocalAsc(dateLeft, dateRight);\n  var difference = Math.abs(differenceInCalendarDays(dateLeft, dateRight));\n  dateLeft.setDate(dateLeft.getDate() - sign * difference); // Math.abs(diff in full days - diff in calendar days) === 1 if last calendar day is not full\n  // If so, result must be decreased by 1 in absolute value\n\n  var isLastDayNotFull = Number(compareLocalAsc(dateLeft, dateRight) === -sign);\n  var result = sign * (difference - isLastDayNotFull); // Prevent negative zero\n\n  return result === 0 ? 0 : result;\n}", "import toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name differenceInMilliseconds\n * @category Millisecond Helpers\n * @summary Get the number of milliseconds between the given dates.\n *\n * @description\n * Get the number of milliseconds between the given dates.\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} dateLeft - the later date\n * @param {Date|Number} dateRight - the earlier date\n * @returns {Number} the number of milliseconds\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // How many milliseconds are between\n * // 2 July 2014 12:30:20.600 and 2 July 2014 12:30:21.700?\n * const result = differenceInMilliseconds(\n *   new Date(2014, 6, 2, 12, 30, 21, 700),\n *   new Date(2014, 6, 2, 12, 30, 20, 600)\n * )\n * //=> 1100\n */\n\nexport default function differenceInMilliseconds(dirtyDateLeft, dirtyDateRight) {\n  requiredArgs(2, arguments);\n  var dateLeft = toDate(dirtyDateLeft);\n  var dateRight = toDate(dirtyDateRight);\n  return dateLeft.getTime() - dateRight.getTime();\n}", "import differenceInMilliseconds from \"../differenceInMilliseconds/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\nvar MILLISECONDS_IN_HOUR = 3600000;\n/**\n * @name differenceInHours\n * @category Hour Helpers\n * @summary Get the number of hours between the given dates.\n *\n * @description\n * Get the number of hours between the given dates.\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} dateLeft - the later date\n * @param {Date|Number} dateRight - the earlier date\n * @returns {Number} the number of hours\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // How many hours are between 2 July 2014 06:50:00 and 2 July 2014 19:00:00?\n * var result = differenceInHours(\n *   new Date(2014, 6, 2, 19, 0),\n *   new Date(2014, 6, 2, 6, 50)\n * )\n * //=> 12\n */\n\nexport default function differenceInHours(dirtyDateLeft, dirtyDateRight) {\n  requiredArgs(2, arguments);\n  var diff = differenceInMilliseconds(dirtyDateLeft, dirtyDateRight) / MILLISECONDS_IN_HOUR;\n  return diff > 0 ? Math.floor(diff) : Math.ceil(diff);\n}", "import differenceInMilliseconds from \"../differenceInMilliseconds/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\nvar MILLISECONDS_IN_MINUTE = 60000;\n/**\n * @name differenceInMinutes\n * @category Minute Helpers\n * @summary Get the number of minutes between the given dates.\n *\n * @description\n * Get the signed number of full (rounded towards 0) minutes between the given dates.\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} dateLeft - the later date\n * @param {Date|Number} dateRight - the earlier date\n * @returns {Number} the number of minutes\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // How many minutes are between 2 July 2014 12:07:59 and 2 July 2014 12:20:00?\n * var result = differenceInMinutes(\n *   new Date(2014, 6, 2, 12, 20, 0),\n *   new Date(2014, 6, 2, 12, 7, 59)\n * )\n * //=> 12\n *\n * @example\n * // How many minutes are from 10:01:59 to 10:00:00\n * var result = differenceInMinutes(\n *   new Date(2000, 0, 1, 10, 0, 0),\n *   new Date(2000, 0, 1, 10, 1, 59)\n * )\n * //=> -1\n */\n\nexport default function differenceInMinutes(dirtyDateLeft, dirtyDateRight) {\n  requiredArgs(2, arguments);\n  var diff = differenceInMilliseconds(dirtyDateLeft, dirtyDateRight) / MILLISECONDS_IN_MINUTE;\n  return diff > 0 ? Math.floor(diff) : Math.ceil(diff);\n}", "import differenceInMilliseconds from \"../differenceInMilliseconds/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name differenceInSeconds\n * @category Second Helpers\n * @summary Get the number of seconds between the given dates.\n *\n * @description\n * Get the number of seconds between the given dates.\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} dateLeft - the later date\n * @param {Date|Number} dateRight - the earlier date\n * @returns {Number} the number of seconds\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // How many seconds are between\n * // 2 July 2014 12:30:07.999 and 2 July 2014 12:30:20.000?\n * const result = differenceInSeconds(\n *   new Date(2014, 6, 2, 12, 30, 20, 0),\n *   new Date(2014, 6, 2, 12, 30, 7, 999)\n * )\n * //=> 12\n */\n\nexport default function differenceInSeconds(dirtyDateLeft, dirtyDateRight) {\n  requiredArgs(2, arguments);\n  var diff = differenceInMilliseconds(dirtyDateLeft, dirtyDateRight) / 1000;\n  return diff > 0 ? Math.floor(diff) : Math.ceil(diff);\n}", "var formatDistanceLocale = {\n  lessThanXSeconds: {\n    one: 'less than a second',\n    other: 'less than {{count}} seconds'\n  },\n  xSeconds: {\n    one: '1 second',\n    other: '{{count}} seconds'\n  },\n  halfAMinute: 'half a minute',\n  lessThanXMinutes: {\n    one: 'less than a minute',\n    other: 'less than {{count}} minutes'\n  },\n  xMinutes: {\n    one: '1 minute',\n    other: '{{count}} minutes'\n  },\n  aboutXHours: {\n    one: 'about 1 hour',\n    other: 'about {{count}} hours'\n  },\n  xHours: {\n    one: '1 hour',\n    other: '{{count}} hours'\n  },\n  xDays: {\n    one: '1 day',\n    other: '{{count}} days'\n  },\n  aboutXWeeks: {\n    one: 'about 1 week',\n    other: 'about {{count}} weeks'\n  },\n  xWeeks: {\n    one: '1 week',\n    other: '{{count}} weeks'\n  },\n  aboutXMonths: {\n    one: 'about 1 month',\n    other: 'about {{count}} months'\n  },\n  xMonths: {\n    one: '1 month',\n    other: '{{count}} months'\n  },\n  aboutXYears: {\n    one: 'about 1 year',\n    other: 'about {{count}} years'\n  },\n  xYears: {\n    one: '1 year',\n    other: '{{count}} years'\n  },\n  overXYears: {\n    one: 'over 1 year',\n    other: 'over {{count}} years'\n  },\n  almostXYears: {\n    one: 'almost 1 year',\n    other: 'almost {{count}} years'\n  }\n};\nexport default function formatDistance(token, count, options) {\n  options = options || {};\n  var result;\n\n  if (typeof formatDistanceLocale[token] === 'string') {\n    result = formatDistanceLocale[token];\n  } else if (count === 1) {\n    result = formatDistanceLocale[token].one;\n  } else {\n    result = formatDistanceLocale[token].other.replace('{{count}}', count);\n  }\n\n  if (options.addSuffix) {\n    if (options.comparison > 0) {\n      return 'in ' + result;\n    } else {\n      return result + ' ago';\n    }\n  }\n\n  return result;\n}", "export default function buildFormatLongFn(args) {\n  return function () {\n    var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n    // TODO: Remove String()\n    var width = options.width ? String(options.width) : args.defaultWidth;\n    var format = args.formats[width] || args.formats[args.defaultWidth];\n    return format;\n  };\n}", "import buildFormatLongFn from \"../../../_lib/buildFormatLongFn/index.js\";\nvar dateFormats = {\n  full: 'EEEE, MMMM do, y',\n  long: 'MMMM do, y',\n  medium: 'MMM d, y',\n  short: 'MM/dd/yyyy'\n};\nvar timeFormats = {\n  full: 'h:mm:ss a zzzz',\n  long: 'h:mm:ss a z',\n  medium: 'h:mm:ss a',\n  short: 'h:mm a'\n};\nvar dateTimeFormats = {\n  full: \"{{date}} 'at' {{time}}\",\n  long: \"{{date}} 'at' {{time}}\",\n  medium: '{{date}}, {{time}}',\n  short: '{{date}}, {{time}}'\n};\nvar formatLong = {\n  date: buildFormatLongFn({\n    formats: dateFormats,\n    defaultWidth: 'full'\n  }),\n  time: buildFormatLongFn({\n    formats: timeFormats,\n    defaultWidth: 'full'\n  }),\n  dateTime: buildFormatLongFn({\n    formats: dateTimeFormats,\n    defaultWidth: 'full'\n  })\n};\nexport default formatLong;", "var formatRelativeLocale = {\n  lastWeek: \"'last' eeee 'at' p\",\n  yesterday: \"'yesterday at' p\",\n  today: \"'today at' p\",\n  tomorrow: \"'tomorrow at' p\",\n  nextWeek: \"eeee 'at' p\",\n  other: 'P'\n};\nexport default function formatRelative(token, _date, _baseDate, _options) {\n  return formatRelativeLocale[token];\n}", "export default function buildLocalizeFn(args) {\n  return function (dirtyIndex, dirtyOptions) {\n    var options = dirtyOptions || {};\n    var context = options.context ? String(options.context) : 'standalone';\n    var valuesArray;\n\n    if (context === 'formatting' && args.formattingValues) {\n      var defaultWidth = args.defaultFormattingWidth || args.defaultWidth;\n      var width = options.width ? String(options.width) : defaultWidth;\n      valuesArray = args.formattingValues[width] || args.formattingValues[defaultWidth];\n    } else {\n      var _defaultWidth = args.defaultWidth;\n\n      var _width = options.width ? String(options.width) : args.defaultWidth;\n\n      valuesArray = args.values[_width] || args.values[_defaultWidth];\n    }\n\n    var index = args.argumentCallback ? args.argumentCallback(dirtyIndex) : dirtyIndex; // @ts-ignore: For some reason TypeScript just don't want to match it, no matter how hard we try. I challange you to try to remove it!\n\n    return valuesArray[index];\n  };\n}", "import buildLocalizeFn from \"../../../_lib/buildLocalizeFn/index.js\";\nvar eraValues = {\n  narrow: ['B', 'A'],\n  abbreviated: ['BC', 'AD'],\n  wide: ['Before Christ', 'Anno Domini']\n};\nvar quarterValues = {\n  narrow: ['1', '2', '3', '4'],\n  abbreviated: ['Q1', 'Q2', 'Q3', 'Q4'],\n  wide: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter']\n}; // Note: in English, the names of days of the week and months are capitalized.\n// If you are making a new locale based on this one, check if the same is true for the language you're working on.\n// Generally, formatted dates should look like they are in the middle of a sentence,\n// e.g. in Spanish language the weekdays and months should be in the lowercase.\n\nvar monthValues = {\n  narrow: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],\n  abbreviated: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],\n  wide: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']\n};\nvar dayValues = {\n  narrow: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],\n  short: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],\n  abbreviated: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],\n  wide: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']\n};\nvar dayPeriodValues = {\n  narrow: {\n    am: 'a',\n    pm: 'p',\n    midnight: 'mi',\n    noon: 'n',\n    morning: 'morning',\n    afternoon: 'afternoon',\n    evening: 'evening',\n    night: 'night'\n  },\n  abbreviated: {\n    am: 'AM',\n    pm: 'PM',\n    midnight: 'midnight',\n    noon: 'noon',\n    morning: 'morning',\n    afternoon: 'afternoon',\n    evening: 'evening',\n    night: 'night'\n  },\n  wide: {\n    am: 'a.m.',\n    pm: 'p.m.',\n    midnight: 'midnight',\n    noon: 'noon',\n    morning: 'morning',\n    afternoon: 'afternoon',\n    evening: 'evening',\n    night: 'night'\n  }\n};\nvar formattingDayPeriodValues = {\n  narrow: {\n    am: 'a',\n    pm: 'p',\n    midnight: 'mi',\n    noon: 'n',\n    morning: 'in the morning',\n    afternoon: 'in the afternoon',\n    evening: 'in the evening',\n    night: 'at night'\n  },\n  abbreviated: {\n    am: 'AM',\n    pm: 'PM',\n    midnight: 'midnight',\n    noon: 'noon',\n    morning: 'in the morning',\n    afternoon: 'in the afternoon',\n    evening: 'in the evening',\n    night: 'at night'\n  },\n  wide: {\n    am: 'a.m.',\n    pm: 'p.m.',\n    midnight: 'midnight',\n    noon: 'noon',\n    morning: 'in the morning',\n    afternoon: 'in the afternoon',\n    evening: 'in the evening',\n    night: 'at night'\n  }\n};\n\nfunction ordinalNumber(dirtyNumber, _dirtyOptions) {\n  var number = Number(dirtyNumber); // If ordinal numbers depend on context, for example,\n  // if they are different for different grammatical genders,\n  // use `options.unit`:\n  //\n  //   var options = dirtyOptions || {}\n  //   var unit = String(options.unit)\n  //\n  // where `unit` can be 'year', 'quarter', 'month', 'week', 'date', 'dayOfYear',\n  // 'day', 'hour', 'minute', 'second'\n\n  var rem100 = number % 100;\n\n  if (rem100 > 20 || rem100 < 10) {\n    switch (rem100 % 10) {\n      case 1:\n        return number + 'st';\n\n      case 2:\n        return number + 'nd';\n\n      case 3:\n        return number + 'rd';\n    }\n  }\n\n  return number + 'th';\n}\n\nvar localize = {\n  ordinalNumber: ordinalNumber,\n  era: buildLocalizeFn({\n    values: eraValues,\n    defaultWidth: 'wide'\n  }),\n  quarter: buildLocalizeFn({\n    values: quarterValues,\n    defaultWidth: 'wide',\n    argumentCallback: function (quarter) {\n      return Number(quarter) - 1;\n    }\n  }),\n  month: buildLocalizeFn({\n    values: monthValues,\n    defaultWidth: 'wide'\n  }),\n  day: buildLocalizeFn({\n    values: dayValues,\n    defaultWidth: 'wide'\n  }),\n  dayPeriod: buildLocalizeFn({\n    values: dayPeriodValues,\n    defaultWidth: 'wide',\n    formattingValues: formattingDayPeriodValues,\n    defaultFormattingWidth: 'wide'\n  })\n};\nexport default localize;", "export default function buildMatchPatternFn(args) {\n  return function (string) {\n    var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n    var matchResult = string.match(args.matchPattern);\n    if (!matchResult) return null;\n    var matchedString = matchResult[0];\n    var parseResult = string.match(args.parsePattern);\n    if (!parseResult) return null;\n    var value = args.valueCallback ? args.valueCallback(parseResult[0]) : parseResult[0];\n    value = options.valueCallback ? options.valueCallback(value) : value;\n    var rest = string.slice(matchedString.length);\n    return {\n      value: value,\n      rest: rest\n    };\n  };\n}", "export default function buildMatchFn(args) {\n  return function (string) {\n    var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n    var width = options.width;\n    var matchPattern = width && args.matchPatterns[width] || args.matchPatterns[args.defaultMatchWidth];\n    var matchResult = string.match(matchPattern);\n\n    if (!matchResult) {\n      return null;\n    }\n\n    var matchedString = matchResult[0];\n    var parsePatterns = width && args.parsePatterns[width] || args.parsePatterns[args.defaultParseWidth];\n    var key = Array.isArray(parsePatterns) ? findIndex(parsePatterns, function (pattern) {\n      return pattern.test(matchedString);\n    }) : findKey(parsePatterns, function (pattern) {\n      return pattern.test(matchedString);\n    });\n    var value;\n    value = args.valueCallback ? args.valueCallback(key) : key;\n    value = options.valueCallback ? options.valueCallback(value) : value;\n    var rest = string.slice(matchedString.length);\n    return {\n      value: value,\n      rest: rest\n    };\n  };\n}\n\nfunction findKey(object, predicate) {\n  for (var key in object) {\n    if (object.hasOwnProperty(key) && predicate(object[key])) {\n      return key;\n    }\n  }\n\n  return undefined;\n}\n\nfunction findIndex(array, predicate) {\n  for (var key = 0; key < array.length; key++) {\n    if (predicate(array[key])) {\n      return key;\n    }\n  }\n\n  return undefined;\n}", "import buildMatchPatternFn from \"../../../_lib/buildMatchPatternFn/index.js\";\nimport buildMatchFn from \"../../../_lib/buildMatchFn/index.js\";\nvar matchOrdinalNumberPattern = /^(\\d+)(th|st|nd|rd)?/i;\nvar parseOrdinalNumberPattern = /\\d+/i;\nvar matchEraPatterns = {\n  narrow: /^(b|a)/i,\n  abbreviated: /^(b\\.?\\s?c\\.?|b\\.?\\s?c\\.?\\s?e\\.?|a\\.?\\s?d\\.?|c\\.?\\s?e\\.?)/i,\n  wide: /^(before christ|before common era|anno domini|common era)/i\n};\nvar parseEraPatterns = {\n  any: [/^b/i, /^(a|c)/i]\n};\nvar matchQuarterPatterns = {\n  narrow: /^[1234]/i,\n  abbreviated: /^q[1234]/i,\n  wide: /^[1234](th|st|nd|rd)? quarter/i\n};\nvar parseQuarterPatterns = {\n  any: [/1/i, /2/i, /3/i, /4/i]\n};\nvar matchMonthPatterns = {\n  narrow: /^[jfmasond]/i,\n  abbreviated: /^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/i,\n  wide: /^(january|february|march|april|may|june|july|august|september|october|november|december)/i\n};\nvar parseMonthPatterns = {\n  narrow: [/^j/i, /^f/i, /^m/i, /^a/i, /^m/i, /^j/i, /^j/i, /^a/i, /^s/i, /^o/i, /^n/i, /^d/i],\n  any: [/^ja/i, /^f/i, /^mar/i, /^ap/i, /^may/i, /^jun/i, /^jul/i, /^au/i, /^s/i, /^o/i, /^n/i, /^d/i]\n};\nvar matchDayPatterns = {\n  narrow: /^[smtwf]/i,\n  short: /^(su|mo|tu|we|th|fr|sa)/i,\n  abbreviated: /^(sun|mon|tue|wed|thu|fri|sat)/i,\n  wide: /^(sunday|monday|tuesday|wednesday|thursday|friday|saturday)/i\n};\nvar parseDayPatterns = {\n  narrow: [/^s/i, /^m/i, /^t/i, /^w/i, /^t/i, /^f/i, /^s/i],\n  any: [/^su/i, /^m/i, /^tu/i, /^w/i, /^th/i, /^f/i, /^sa/i]\n};\nvar matchDayPeriodPatterns = {\n  narrow: /^(a|p|mi|n|(in the|at) (morning|afternoon|evening|night))/i,\n  any: /^([ap]\\.?\\s?m\\.?|midnight|noon|(in the|at) (morning|afternoon|evening|night))/i\n};\nvar parseDayPeriodPatterns = {\n  any: {\n    am: /^a/i,\n    pm: /^p/i,\n    midnight: /^mi/i,\n    noon: /^no/i,\n    morning: /morning/i,\n    afternoon: /afternoon/i,\n    evening: /evening/i,\n    night: /night/i\n  }\n};\nvar match = {\n  ordinalNumber: buildMatchPatternFn({\n    matchPattern: matchOrdinalNumberPattern,\n    parsePattern: parseOrdinalNumberPattern,\n    valueCallback: function (value) {\n      return parseInt(value, 10);\n    }\n  }),\n  era: buildMatchFn({\n    matchPatterns: matchEraPatterns,\n    defaultMatchWidth: 'wide',\n    parsePatterns: parseEraPatterns,\n    defaultParseWidth: 'any'\n  }),\n  quarter: buildMatchFn({\n    matchPatterns: matchQuarterPatterns,\n    defaultMatchWidth: 'wide',\n    parsePatterns: parseQuarterPatterns,\n    defaultParseWidth: 'any',\n    valueCallback: function (index) {\n      return index + 1;\n    }\n  }),\n  month: buildMatchFn({\n    matchPatterns: matchMonthPatterns,\n    defaultMatchWidth: 'wide',\n    parsePatterns: parseMonthPatterns,\n    defaultParseWidth: 'any'\n  }),\n  day: buildMatchFn({\n    matchPatterns: matchDayPatterns,\n    defaultMatchWidth: 'wide',\n    parsePatterns: parseDayPatterns,\n    defaultParseWidth: 'any'\n  }),\n  dayPeriod: buildMatchFn({\n    matchPatterns: matchDayPeriodPatterns,\n    defaultMatchWidth: 'any',\n    parsePatterns: parseDayPeriodPatterns,\n    defaultParseWidth: 'any'\n  })\n};\nexport default match;", "import formatDistance from \"./_lib/formatDistance/index.js\";\nimport formatLong from \"./_lib/formatLong/index.js\";\nimport formatRelative from \"./_lib/formatRelative/index.js\";\nimport localize from \"./_lib/localize/index.js\";\nimport match from \"./_lib/match/index.js\";\n/**\n * @type {Locale}\n * @category Locales\n * @summary English locale (United States).\n * @language English\n * @iso-639-2 eng\n * @author Sasha Koss [@kossnocorp]{@link https://github.com/kossnocorp}\n * @author Lesha Koss [@leshakoss]{@link https://github.com/leshakoss}\n */\n\nvar locale = {\n  code: 'en-US',\n  formatDistance: formatDistance,\n  formatLong: formatLong,\n  formatRelative: formatRelative,\n  localize: localize,\n  match: match,\n  options: {\n    weekStartsOn: 0\n    /* Sunday */\n    ,\n    firstWeekContainsDate: 1\n  }\n};\nexport default locale;", "import toInteger from \"../_lib/toInteger/index.js\";\nimport addMilliseconds from \"../addMilliseconds/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name subMilliseconds\n * @category Millisecond Helpers\n * @summary Subtract the specified number of milliseconds from the given date.\n *\n * @description\n * Subtract the specified number of milliseconds from the given date.\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} date - the date to be changed\n * @param {Number} amount - the amount of milliseconds to be subtracted. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.\n * @returns {Date} the new date with the milliseconds subtracted\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // Subtract 750 milliseconds from 10 July 2014 12:45:30.000:\n * const result = subMilliseconds(new Date(2014, 6, 10, 12, 45, 30, 0), 750)\n * //=> Thu Jul 10 2014 12:45:29.250\n */\n\nexport default function subMilliseconds(dirtyDate, dirtyAmount) {\n  requiredArgs(2, arguments);\n  var amount = toInteger(dirtyAmount);\n  return addMilliseconds(dirtyDate, -amount);\n}", "export default function addLeadingZeros(number, targetLength) {\n  var sign = number < 0 ? '-' : '';\n  var output = Math.abs(number).toString();\n\n  while (output.length < targetLength) {\n    output = '0' + output;\n  }\n\n  return sign + output;\n}", "import addLeadingZeros from \"../../addLeadingZeros/index.js\";\n/*\n * |     | Unit                           |     | Unit                           |\n * |-----|--------------------------------|-----|--------------------------------|\n * |  a  | AM, PM                         |  A* |                                |\n * |  d  | Day of month                   |  D  |                                |\n * |  h  | Hour [1-12]                    |  H  | Hour [0-23]                    |\n * |  m  | Minute                         |  M  | Month                          |\n * |  s  | Second                         |  S  | Fraction of second             |\n * |  y  | Year (abs)                     |  Y  |                                |\n *\n * Letters marked by * are not implemented but reserved by Unicode standard.\n */\n\nvar formatters = {\n  // Year\n  y: function (date, token) {\n    // From http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Format_tokens\n    // | Year     |     y | yy |   yyy |  yyyy | yyyyy |\n    // |----------|-------|----|-------|-------|-------|\n    // | AD 1     |     1 | 01 |   001 |  0001 | 00001 |\n    // | AD 12    |    12 | 12 |   012 |  0012 | 00012 |\n    // | AD 123   |   123 | 23 |   123 |  0123 | 00123 |\n    // | AD 1234  |  1234 | 34 |  1234 |  1234 | 01234 |\n    // | AD 12345 | 12345 | 45 | 12345 | 12345 | 12345 |\n    var signedYear = date.getUTCFullYear(); // Returns 1 for 1 BC (which is year 0 in JavaScript)\n\n    var year = signedYear > 0 ? signedYear : 1 - signedYear;\n    return addLeadingZeros(token === 'yy' ? year % 100 : year, token.length);\n  },\n  // Month\n  M: function (date, token) {\n    var month = date.getUTCMonth();\n    return token === 'M' ? String(month + 1) : addLeadingZeros(month + 1, 2);\n  },\n  // Day of the month\n  d: function (date, token) {\n    return addLeadingZeros(date.getUTCDate(), token.length);\n  },\n  // AM or PM\n  a: function (date, token) {\n    var dayPeriodEnumValue = date.getUTCHours() / 12 >= 1 ? 'pm' : 'am';\n\n    switch (token) {\n      case 'a':\n      case 'aa':\n        return dayPeriodEnumValue.toUpperCase();\n\n      case 'aaa':\n        return dayPeriodEnumValue;\n\n      case 'aaaaa':\n        return dayPeriodEnumValue[0];\n\n      case 'aaaa':\n      default:\n        return dayPeriodEnumValue === 'am' ? 'a.m.' : 'p.m.';\n    }\n  },\n  // Hour [1-12]\n  h: function (date, token) {\n    return addLeadingZeros(date.getUTCHours() % 12 || 12, token.length);\n  },\n  // Hour [0-23]\n  H: function (date, token) {\n    return addLeadingZeros(date.getUTCHours(), token.length);\n  },\n  // Minute\n  m: function (date, token) {\n    return addLeadingZeros(date.getUTCMinutes(), token.length);\n  },\n  // Second\n  s: function (date, token) {\n    return addLeadingZeros(date.getUTCSeconds(), token.length);\n  },\n  // Fraction of second\n  S: function (date, token) {\n    var numberOfDigits = token.length;\n    var milliseconds = date.getUTCMilliseconds();\n    var fractionalSeconds = Math.floor(milliseconds * Math.pow(10, numberOfDigits - 3));\n    return addLeadingZeros(fractionalSeconds, token.length);\n  }\n};\nexport default formatters;", "import toDate from \"../../toDate/index.js\";\nimport requiredArgs from \"../requiredArgs/index.js\";\nvar MILLISECONDS_IN_DAY = 86400000; // This function will be a part of public API when UTC function will be implemented.\n// See issue: https://github.com/date-fns/date-fns/issues/376\n\nexport default function getUTCDayOfYear(dirtyDate) {\n  requiredArgs(1, arguments);\n  var date = toDate(dirtyDate);\n  var timestamp = date.getTime();\n  date.setUTCMonth(0, 1);\n  date.setUTCHours(0, 0, 0, 0);\n  var startOfYearTimestamp = date.getTime();\n  var difference = timestamp - startOfYearTimestamp;\n  return Math.floor(difference / MILLISECONDS_IN_DAY) + 1;\n}", "import toDate from \"../../toDate/index.js\";\nimport requiredArgs from \"../requiredArgs/index.js\"; // This function will be a part of public API when UTC function will be implemented.\n// See issue: https://github.com/date-fns/date-fns/issues/376\n\nexport default function startOfUTCISOWeek(dirtyDate) {\n  requiredArgs(1, arguments);\n  var weekStartsOn = 1;\n  var date = toDate(dirtyDate);\n  var day = date.getUTCDay();\n  var diff = (day < weekStartsOn ? 7 : 0) + day - weekStartsOn;\n  date.setUTCDate(date.getUTCDate() - diff);\n  date.setUTCHours(0, 0, 0, 0);\n  return date;\n}", "import toDate from \"../../toDate/index.js\";\nimport startOfUTCISOWeek from \"../startOfUTCISOWeek/index.js\";\nimport requiredArgs from \"../requiredArgs/index.js\"; // This function will be a part of public API when UTC function will be implemented.\n// See issue: https://github.com/date-fns/date-fns/issues/376\n\nexport default function getUTCISOWeekYear(dirtyDate) {\n  requiredArgs(1, arguments);\n  var date = toDate(dirtyDate);\n  var year = date.getUTCFullYear();\n  var fourthOfJanuaryOfNextYear = new Date(0);\n  fourthOfJanuaryOfNextYear.setUTCFullYear(year + 1, 0, 4);\n  fourthOfJanuaryOfNextYear.setUTCHours(0, 0, 0, 0);\n  var startOfNextYear = startOfUTCISOWeek(fourthOfJanuaryOfNextYear);\n  var fourthOfJanuaryOfThisYear = new Date(0);\n  fourthOfJanuaryOfThisYear.setUTCFullYear(year, 0, 4);\n  fourthOfJanuaryOfThisYear.setUTCHours(0, 0, 0, 0);\n  var startOfThisYear = startOfUTCISOWeek(fourthOfJanuaryOfThisYear);\n\n  if (date.getTime() >= startOfNextYear.getTime()) {\n    return year + 1;\n  } else if (date.getTime() >= startOfThisYear.getTime()) {\n    return year;\n  } else {\n    return year - 1;\n  }\n}", "import getUTCISOWeekYear from \"../getUTCISOWeekYear/index.js\";\nimport startOfUTCISOWeek from \"../startOfUTCISOWeek/index.js\";\nimport requiredArgs from \"../requiredArgs/index.js\"; // This function will be a part of public API when UTC function will be implemented.\n// See issue: https://github.com/date-fns/date-fns/issues/376\n\nexport default function startOfUTCISOWeekYear(dirtyDate) {\n  requiredArgs(1, arguments);\n  var year = getUTCISOWeekYear(dirtyDate);\n  var fourthOfJanuary = new Date(0);\n  fourthOfJanuary.setUTCFullYear(year, 0, 4);\n  fourthOfJanuary.setUTCHours(0, 0, 0, 0);\n  var date = startOfUTCISOWeek(fourthOfJanuary);\n  return date;\n}", "import toDate from \"../../toDate/index.js\";\nimport startOfUTCISOWeek from \"../startOfUTCISOWeek/index.js\";\nimport startOfUTCISOWeekYear from \"../startOfUTCISOWeekYear/index.js\";\nimport requiredArgs from \"../requiredArgs/index.js\";\nvar MILLISECONDS_IN_WEEK = 604800000; // This function will be a part of public API when UTC function will be implemented.\n// See issue: https://github.com/date-fns/date-fns/issues/376\n\nexport default function getUTCISOWeek(dirtyDate) {\n  requiredArgs(1, arguments);\n  var date = toDate(dirtyDate);\n  var diff = startOfUTCISOWeek(date).getTime() - startOfUTCISOWeekYear(date).getTime(); // Round the number of days to the nearest integer\n  // because the number of milliseconds in a week is not constant\n  // (e.g. it's different in the week of the daylight saving time clock shift)\n\n  return Math.round(diff / MILLISECONDS_IN_WEEK) + 1;\n}", "import toInteger from \"../toInteger/index.js\";\nimport toDate from \"../../toDate/index.js\";\nimport requiredArgs from \"../requiredArgs/index.js\"; // This function will be a part of public API when UTC function will be implemented.\n// See issue: https://github.com/date-fns/date-fns/issues/376\n\nexport default function startOfUTCWeek(dirtyDate, dirtyOptions) {\n  requiredArgs(1, arguments);\n  var options = dirtyOptions || {};\n  var locale = options.locale;\n  var localeWeekStartsOn = locale && locale.options && locale.options.weekStartsOn;\n  var defaultWeekStartsOn = localeWeekStartsOn == null ? 0 : toInteger(localeWeekStartsOn);\n  var weekStartsOn = options.weekStartsOn == null ? defaultWeekStartsOn : toInteger(options.weekStartsOn); // Test if weekStartsOn is between 0 and 6 _and_ is not NaN\n\n  if (!(weekStartsOn >= 0 && weekStartsOn <= 6)) {\n    throw new RangeError('weekStartsOn must be between 0 and 6 inclusively');\n  }\n\n  var date = toDate(dirtyDate);\n  var day = date.getUTCDay();\n  var diff = (day < weekStartsOn ? 7 : 0) + day - weekStartsOn;\n  date.setUTCDate(date.getUTCDate() - diff);\n  date.setUTCHours(0, 0, 0, 0);\n  return date;\n}", "import toInteger from \"../toInteger/index.js\";\nimport toDate from \"../../toDate/index.js\";\nimport startOfUTCWeek from \"../startOfUTCWeek/index.js\";\nimport requiredArgs from \"../requiredArgs/index.js\"; // This function will be a part of public API when UTC function will be implemented.\n// See issue: https://github.com/date-fns/date-fns/issues/376\n\nexport default function getUTCWeekYear(dirtyDate, dirtyOptions) {\n  requiredArgs(1, arguments);\n  var date = toDate(dirtyDate, dirtyOptions);\n  var year = date.getUTCFullYear();\n  var options = dirtyOptions || {};\n  var locale = options.locale;\n  var localeFirstWeekContainsDate = locale && locale.options && locale.options.firstWeekContainsDate;\n  var defaultFirstWeekContainsDate = localeFirstWeekContainsDate == null ? 1 : toInteger(localeFirstWeekContainsDate);\n  var firstWeekContainsDate = options.firstWeekContainsDate == null ? defaultFirstWeekContainsDate : toInteger(options.firstWeekContainsDate); // Test if weekStartsOn is between 1 and 7 _and_ is not NaN\n\n  if (!(firstWeekContainsDate >= 1 && firstWeekContainsDate <= 7)) {\n    throw new RangeError('firstWeekContainsDate must be between 1 and 7 inclusively');\n  }\n\n  var firstWeekOfNextYear = new Date(0);\n  firstWeekOfNextYear.setUTCFullYear(year + 1, 0, firstWeekContainsDate);\n  firstWeekOfNextYear.setUTCHours(0, 0, 0, 0);\n  var startOfNextYear = startOfUTCWeek(firstWeekOfNextYear, dirtyOptions);\n  var firstWeekOfThisYear = new Date(0);\n  firstWeekOfThisYear.setUTCFullYear(year, 0, firstWeekContainsDate);\n  firstWeekOfThisYear.setUTCHours(0, 0, 0, 0);\n  var startOfThisYear = startOfUTCWeek(firstWeekOfThisYear, dirtyOptions);\n\n  if (date.getTime() >= startOfNextYear.getTime()) {\n    return year + 1;\n  } else if (date.getTime() >= startOfThisYear.getTime()) {\n    return year;\n  } else {\n    return year - 1;\n  }\n}", "import toInteger from \"../toInteger/index.js\";\nimport getUTCWeekYear from \"../getUTCWeekYear/index.js\";\nimport startOfUTCWeek from \"../startOfUTCWeek/index.js\";\nimport requiredArgs from \"../requiredArgs/index.js\"; // This function will be a part of public API when UTC function will be implemented.\n// See issue: https://github.com/date-fns/date-fns/issues/376\n\nexport default function startOfUTCWeekYear(dirtyDate, dirtyOptions) {\n  requiredArgs(1, arguments);\n  var options = dirtyOptions || {};\n  var locale = options.locale;\n  var localeFirstWeekContainsDate = locale && locale.options && locale.options.firstWeekContainsDate;\n  var defaultFirstWeekContainsDate = localeFirstWeekContainsDate == null ? 1 : toInteger(localeFirstWeekContainsDate);\n  var firstWeekContainsDate = options.firstWeekContainsDate == null ? defaultFirstWeekContainsDate : toInteger(options.firstWeekContainsDate);\n  var year = getUTCWeekYear(dirtyDate, dirtyOptions);\n  var firstWeek = new Date(0);\n  firstWeek.setUTCFullYear(year, 0, firstWeekContainsDate);\n  firstWeek.setUTCHours(0, 0, 0, 0);\n  var date = startOfUTCWeek(firstWeek, dirtyOptions);\n  return date;\n}", "import toDate from \"../../toDate/index.js\";\nimport startOfUTCWeek from \"../startOfUTCWeek/index.js\";\nimport startOfUTCWeekYear from \"../startOfUTCWeekYear/index.js\";\nimport requiredArgs from \"../requiredArgs/index.js\";\nvar MILLISECONDS_IN_WEEK = 604800000; // This function will be a part of public API when UTC function will be implemented.\n// See issue: https://github.com/date-fns/date-fns/issues/376\n\nexport default function getUTCWeek(dirtyDate, options) {\n  requiredArgs(1, arguments);\n  var date = toDate(dirtyDate);\n  var diff = startOfUTCWeek(date, options).getTime() - startOfUTCWeekYear(date, options).getTime(); // Round the number of days to the nearest integer\n  // because the number of milliseconds in a week is not constant\n  // (e.g. it's different in the week of the daylight saving time clock shift)\n\n  return Math.round(diff / MILLISECONDS_IN_WEEK) + 1;\n}", "import lightFormatters from \"../lightFormatters/index.js\";\nimport getUTCDayOfYear from \"../../../_lib/getUTCDayOfYear/index.js\";\nimport getUTCISOWeek from \"../../../_lib/getUTCISOWeek/index.js\";\nimport getUTCISOWeekYear from \"../../../_lib/getUTCISOWeekYear/index.js\";\nimport getUTCWeek from \"../../../_lib/getUTCWeek/index.js\";\nimport getUTCWeekYear from \"../../../_lib/getUTCWeekYear/index.js\";\nimport addLeadingZeros from \"../../addLeadingZeros/index.js\";\nvar dayPeriodEnum = {\n  am: 'am',\n  pm: 'pm',\n  midnight: 'midnight',\n  noon: 'noon',\n  morning: 'morning',\n  afternoon: 'afternoon',\n  evening: 'evening',\n  night: 'night'\n};\n/*\n * |     | Unit                           |     | Unit                           |\n * |-----|--------------------------------|-----|--------------------------------|\n * |  a  | AM, PM                         |  A* | Milliseconds in day            |\n * |  b  | AM, PM, noon, midnight         |  B  | Flexible day period            |\n * |  c  | Stand-alone local day of week  |  C* | Localized hour w/ day period   |\n * |  d  | Day of month                   |  D  | Day of year                    |\n * |  e  | Local day of week              |  E  | Day of week                    |\n * |  f  |                                |  F* | Day of week in month           |\n * |  g* | Modified Julian day            |  G  | Era                            |\n * |  h  | Hour [1-12]                    |  H  | Hour [0-23]                    |\n * |  i! | ISO day of week                |  I! | ISO week of year               |\n * |  j* | Localized hour w/ day period   |  J* | Localized hour w/o day period  |\n * |  k  | Hour [1-24]                    |  K  | Hour [0-11]                    |\n * |  l* | (deprecated)                   |  L  | Stand-alone month              |\n * |  m  | Minute                         |  M  | Month                          |\n * |  n  |                                |  N  |                                |\n * |  o! | Ordinal number modifier        |  O  | Timezone (GMT)                 |\n * |  p! | Long localized time            |  P! | Long localized date            |\n * |  q  | Stand-alone quarter            |  Q  | Quarter                        |\n * |  r* | Related Gregorian year         |  R! | ISO week-numbering year        |\n * |  s  | Second                         |  S  | Fraction of second             |\n * |  t! | Seconds timestamp              |  T! | Milliseconds timestamp         |\n * |  u  | Extended year                  |  U* | Cyclic year                    |\n * |  v* | Timezone (generic non-locat.)  |  V* | Timezone (location)            |\n * |  w  | Local week of year             |  W* | Week of month                  |\n * |  x  | Timezone (ISO-8601 w/o Z)      |  X  | Timezone (ISO-8601)            |\n * |  y  | Year (abs)                     |  Y  | Local week-numbering year      |\n * |  z  | Timezone (specific non-locat.) |  Z* | Timezone (aliases)             |\n *\n * Letters marked by * are not implemented but reserved by Unicode standard.\n *\n * Letters marked by ! are non-standard, but implemented by date-fns:\n * - `o` modifies the previous token to turn it into an ordinal (see `format` docs)\n * - `i` is ISO day of week. For `i` and `ii` is returns numeric ISO week days,\n *   i.e. 7 for Sunday, 1 for Monday, etc.\n * - `I` is ISO week of year, as opposed to `w` which is local week of year.\n * - `R` is ISO week-numbering year, as opposed to `Y` which is local week-numbering year.\n *   `R` is supposed to be used in conjunction with `I` and `i`\n *   for universal ISO week-numbering date, whereas\n *   `Y` is supposed to be used in conjunction with `w` and `e`\n *   for week-numbering date specific to the locale.\n * - `P` is long localized date format\n * - `p` is long localized time format\n */\n\nvar formatters = {\n  // Era\n  G: function (date, token, localize) {\n    var era = date.getUTCFullYear() > 0 ? 1 : 0;\n\n    switch (token) {\n      // AD, BC\n      case 'G':\n      case 'GG':\n      case 'GGG':\n        return localize.era(era, {\n          width: 'abbreviated'\n        });\n      // A, B\n\n      case 'GGGGG':\n        return localize.era(era, {\n          width: 'narrow'\n        });\n      // Anno Domini, Before Christ\n\n      case 'GGGG':\n      default:\n        return localize.era(era, {\n          width: 'wide'\n        });\n    }\n  },\n  // Year\n  y: function (date, token, localize) {\n    // Ordinal number\n    if (token === 'yo') {\n      var signedYear = date.getUTCFullYear(); // Returns 1 for 1 BC (which is year 0 in JavaScript)\n\n      var year = signedYear > 0 ? signedYear : 1 - signedYear;\n      return localize.ordinalNumber(year, {\n        unit: 'year'\n      });\n    }\n\n    return lightFormatters.y(date, token);\n  },\n  // Local week-numbering year\n  Y: function (date, token, localize, options) {\n    var signedWeekYear = getUTCWeekYear(date, options); // Returns 1 for 1 BC (which is year 0 in JavaScript)\n\n    var weekYear = signedWeekYear > 0 ? signedWeekYear : 1 - signedWeekYear; // Two digit year\n\n    if (token === 'YY') {\n      var twoDigitYear = weekYear % 100;\n      return addLeadingZeros(twoDigitYear, 2);\n    } // Ordinal number\n\n\n    if (token === 'Yo') {\n      return localize.ordinalNumber(weekYear, {\n        unit: 'year'\n      });\n    } // Padding\n\n\n    return addLeadingZeros(weekYear, token.length);\n  },\n  // ISO week-numbering year\n  R: function (date, token) {\n    var isoWeekYear = getUTCISOWeekYear(date); // Padding\n\n    return addLeadingZeros(isoWeekYear, token.length);\n  },\n  // Extended year. This is a single number designating the year of this calendar system.\n  // The main difference between `y` and `u` localizers are B.C. years:\n  // | Year | `y` | `u` |\n  // |------|-----|-----|\n  // | AC 1 |   1 |   1 |\n  // | BC 1 |   1 |   0 |\n  // | BC 2 |   2 |  -1 |\n  // Also `yy` always returns the last two digits of a year,\n  // while `uu` pads single digit years to 2 characters and returns other years unchanged.\n  u: function (date, token) {\n    var year = date.getUTCFullYear();\n    return addLeadingZeros(year, token.length);\n  },\n  // Quarter\n  Q: function (date, token, localize) {\n    var quarter = Math.ceil((date.getUTCMonth() + 1) / 3);\n\n    switch (token) {\n      // 1, 2, 3, 4\n      case 'Q':\n        return String(quarter);\n      // 01, 02, 03, 04\n\n      case 'QQ':\n        return addLeadingZeros(quarter, 2);\n      // 1st, 2nd, 3rd, 4th\n\n      case 'Qo':\n        return localize.ordinalNumber(quarter, {\n          unit: 'quarter'\n        });\n      // Q1, Q2, Q3, Q4\n\n      case 'QQQ':\n        return localize.quarter(quarter, {\n          width: 'abbreviated',\n          context: 'formatting'\n        });\n      // 1, 2, 3, 4 (narrow quarter; could be not numerical)\n\n      case 'QQQQQ':\n        return localize.quarter(quarter, {\n          width: 'narrow',\n          context: 'formatting'\n        });\n      // 1st quarter, 2nd quarter, ...\n\n      case 'QQQQ':\n      default:\n        return localize.quarter(quarter, {\n          width: 'wide',\n          context: 'formatting'\n        });\n    }\n  },\n  // Stand-alone quarter\n  q: function (date, token, localize) {\n    var quarter = Math.ceil((date.getUTCMonth() + 1) / 3);\n\n    switch (token) {\n      // 1, 2, 3, 4\n      case 'q':\n        return String(quarter);\n      // 01, 02, 03, 04\n\n      case 'qq':\n        return addLeadingZeros(quarter, 2);\n      // 1st, 2nd, 3rd, 4th\n\n      case 'qo':\n        return localize.ordinalNumber(quarter, {\n          unit: 'quarter'\n        });\n      // Q1, Q2, Q3, Q4\n\n      case 'qqq':\n        return localize.quarter(quarter, {\n          width: 'abbreviated',\n          context: 'standalone'\n        });\n      // 1, 2, 3, 4 (narrow quarter; could be not numerical)\n\n      case 'qqqqq':\n        return localize.quarter(quarter, {\n          width: 'narrow',\n          context: 'standalone'\n        });\n      // 1st quarter, 2nd quarter, ...\n\n      case 'qqqq':\n      default:\n        return localize.quarter(quarter, {\n          width: 'wide',\n          context: 'standalone'\n        });\n    }\n  },\n  // Month\n  M: function (date, token, localize) {\n    var month = date.getUTCMonth();\n\n    switch (token) {\n      case 'M':\n      case 'MM':\n        return lightFormatters.M(date, token);\n      // 1st, 2nd, ..., 12th\n\n      case 'Mo':\n        return localize.ordinalNumber(month + 1, {\n          unit: 'month'\n        });\n      // Jan, Feb, ..., Dec\n\n      case 'MMM':\n        return localize.month(month, {\n          width: 'abbreviated',\n          context: 'formatting'\n        });\n      // J, F, ..., D\n\n      case 'MMMMM':\n        return localize.month(month, {\n          width: 'narrow',\n          context: 'formatting'\n        });\n      // January, February, ..., December\n\n      case 'MMMM':\n      default:\n        return localize.month(month, {\n          width: 'wide',\n          context: 'formatting'\n        });\n    }\n  },\n  // Stand-alone month\n  L: function (date, token, localize) {\n    var month = date.getUTCMonth();\n\n    switch (token) {\n      // 1, 2, ..., 12\n      case 'L':\n        return String(month + 1);\n      // 01, 02, ..., 12\n\n      case 'LL':\n        return addLeadingZeros(month + 1, 2);\n      // 1st, 2nd, ..., 12th\n\n      case 'Lo':\n        return localize.ordinalNumber(month + 1, {\n          unit: 'month'\n        });\n      // Jan, Feb, ..., Dec\n\n      case 'LLL':\n        return localize.month(month, {\n          width: 'abbreviated',\n          context: 'standalone'\n        });\n      // J, F, ..., D\n\n      case 'LLLLL':\n        return localize.month(month, {\n          width: 'narrow',\n          context: 'standalone'\n        });\n      // January, February, ..., December\n\n      case 'LLLL':\n      default:\n        return localize.month(month, {\n          width: 'wide',\n          context: 'standalone'\n        });\n    }\n  },\n  // Local week of year\n  w: function (date, token, localize, options) {\n    var week = getUTCWeek(date, options);\n\n    if (token === 'wo') {\n      return localize.ordinalNumber(week, {\n        unit: 'week'\n      });\n    }\n\n    return addLeadingZeros(week, token.length);\n  },\n  // ISO week of year\n  I: function (date, token, localize) {\n    var isoWeek = getUTCISOWeek(date);\n\n    if (token === 'Io') {\n      return localize.ordinalNumber(isoWeek, {\n        unit: 'week'\n      });\n    }\n\n    return addLeadingZeros(isoWeek, token.length);\n  },\n  // Day of the month\n  d: function (date, token, localize) {\n    if (token === 'do') {\n      return localize.ordinalNumber(date.getUTCDate(), {\n        unit: 'date'\n      });\n    }\n\n    return lightFormatters.d(date, token);\n  },\n  // Day of year\n  D: function (date, token, localize) {\n    var dayOfYear = getUTCDayOfYear(date);\n\n    if (token === 'Do') {\n      return localize.ordinalNumber(dayOfYear, {\n        unit: 'dayOfYear'\n      });\n    }\n\n    return addLeadingZeros(dayOfYear, token.length);\n  },\n  // Day of week\n  E: function (date, token, localize) {\n    var dayOfWeek = date.getUTCDay();\n\n    switch (token) {\n      // Tue\n      case 'E':\n      case 'EE':\n      case 'EEE':\n        return localize.day(dayOfWeek, {\n          width: 'abbreviated',\n          context: 'formatting'\n        });\n      // T\n\n      case 'EEEEE':\n        return localize.day(dayOfWeek, {\n          width: 'narrow',\n          context: 'formatting'\n        });\n      // Tu\n\n      case 'EEEEEE':\n        return localize.day(dayOfWeek, {\n          width: 'short',\n          context: 'formatting'\n        });\n      // Tuesday\n\n      case 'EEEE':\n      default:\n        return localize.day(dayOfWeek, {\n          width: 'wide',\n          context: 'formatting'\n        });\n    }\n  },\n  // Local day of week\n  e: function (date, token, localize, options) {\n    var dayOfWeek = date.getUTCDay();\n    var localDayOfWeek = (dayOfWeek - options.weekStartsOn + 8) % 7 || 7;\n\n    switch (token) {\n      // Numerical value (Nth day of week with current locale or weekStartsOn)\n      case 'e':\n        return String(localDayOfWeek);\n      // Padded numerical value\n\n      case 'ee':\n        return addLeadingZeros(localDayOfWeek, 2);\n      // 1st, 2nd, ..., 7th\n\n      case 'eo':\n        return localize.ordinalNumber(localDayOfWeek, {\n          unit: 'day'\n        });\n\n      case 'eee':\n        return localize.day(dayOfWeek, {\n          width: 'abbreviated',\n          context: 'formatting'\n        });\n      // T\n\n      case 'eeeee':\n        return localize.day(dayOfWeek, {\n          width: 'narrow',\n          context: 'formatting'\n        });\n      // Tu\n\n      case 'eeeeee':\n        return localize.day(dayOfWeek, {\n          width: 'short',\n          context: 'formatting'\n        });\n      // Tuesday\n\n      case 'eeee':\n      default:\n        return localize.day(dayOfWeek, {\n          width: 'wide',\n          context: 'formatting'\n        });\n    }\n  },\n  // Stand-alone local day of week\n  c: function (date, token, localize, options) {\n    var dayOfWeek = date.getUTCDay();\n    var localDayOfWeek = (dayOfWeek - options.weekStartsOn + 8) % 7 || 7;\n\n    switch (token) {\n      // Numerical value (same as in `e`)\n      case 'c':\n        return String(localDayOfWeek);\n      // Padded numerical value\n\n      case 'cc':\n        return addLeadingZeros(localDayOfWeek, token.length);\n      // 1st, 2nd, ..., 7th\n\n      case 'co':\n        return localize.ordinalNumber(localDayOfWeek, {\n          unit: 'day'\n        });\n\n      case 'ccc':\n        return localize.day(dayOfWeek, {\n          width: 'abbreviated',\n          context: 'standalone'\n        });\n      // T\n\n      case 'ccccc':\n        return localize.day(dayOfWeek, {\n          width: 'narrow',\n          context: 'standalone'\n        });\n      // Tu\n\n      case 'cccccc':\n        return localize.day(dayOfWeek, {\n          width: 'short',\n          context: 'standalone'\n        });\n      // Tuesday\n\n      case 'cccc':\n      default:\n        return localize.day(dayOfWeek, {\n          width: 'wide',\n          context: 'standalone'\n        });\n    }\n  },\n  // ISO day of week\n  i: function (date, token, localize) {\n    var dayOfWeek = date.getUTCDay();\n    var isoDayOfWeek = dayOfWeek === 0 ? 7 : dayOfWeek;\n\n    switch (token) {\n      // 2\n      case 'i':\n        return String(isoDayOfWeek);\n      // 02\n\n      case 'ii':\n        return addLeadingZeros(isoDayOfWeek, token.length);\n      // 2nd\n\n      case 'io':\n        return localize.ordinalNumber(isoDayOfWeek, {\n          unit: 'day'\n        });\n      // Tue\n\n      case 'iii':\n        return localize.day(dayOfWeek, {\n          width: 'abbreviated',\n          context: 'formatting'\n        });\n      // T\n\n      case 'iiiii':\n        return localize.day(dayOfWeek, {\n          width: 'narrow',\n          context: 'formatting'\n        });\n      // Tu\n\n      case 'iiiiii':\n        return localize.day(dayOfWeek, {\n          width: 'short',\n          context: 'formatting'\n        });\n      // Tuesday\n\n      case 'iiii':\n      default:\n        return localize.day(dayOfWeek, {\n          width: 'wide',\n          context: 'formatting'\n        });\n    }\n  },\n  // AM or PM\n  a: function (date, token, localize) {\n    var hours = date.getUTCHours();\n    var dayPeriodEnumValue = hours / 12 >= 1 ? 'pm' : 'am';\n\n    switch (token) {\n      case 'a':\n      case 'aa':\n        return localize.dayPeriod(dayPeriodEnumValue, {\n          width: 'abbreviated',\n          context: 'formatting'\n        });\n\n      case 'aaa':\n        return localize.dayPeriod(dayPeriodEnumValue, {\n          width: 'abbreviated',\n          context: 'formatting'\n        }).toLowerCase();\n\n      case 'aaaaa':\n        return localize.dayPeriod(dayPeriodEnumValue, {\n          width: 'narrow',\n          context: 'formatting'\n        });\n\n      case 'aaaa':\n      default:\n        return localize.dayPeriod(dayPeriodEnumValue, {\n          width: 'wide',\n          context: 'formatting'\n        });\n    }\n  },\n  // AM, PM, midnight, noon\n  b: function (date, token, localize) {\n    var hours = date.getUTCHours();\n    var dayPeriodEnumValue;\n\n    if (hours === 12) {\n      dayPeriodEnumValue = dayPeriodEnum.noon;\n    } else if (hours === 0) {\n      dayPeriodEnumValue = dayPeriodEnum.midnight;\n    } else {\n      dayPeriodEnumValue = hours / 12 >= 1 ? 'pm' : 'am';\n    }\n\n    switch (token) {\n      case 'b':\n      case 'bb':\n        return localize.dayPeriod(dayPeriodEnumValue, {\n          width: 'abbreviated',\n          context: 'formatting'\n        });\n\n      case 'bbb':\n        return localize.dayPeriod(dayPeriodEnumValue, {\n          width: 'abbreviated',\n          context: 'formatting'\n        }).toLowerCase();\n\n      case 'bbbbb':\n        return localize.dayPeriod(dayPeriodEnumValue, {\n          width: 'narrow',\n          context: 'formatting'\n        });\n\n      case 'bbbb':\n      default:\n        return localize.dayPeriod(dayPeriodEnumValue, {\n          width: 'wide',\n          context: 'formatting'\n        });\n    }\n  },\n  // in the morning, in the afternoon, in the evening, at night\n  B: function (date, token, localize) {\n    var hours = date.getUTCHours();\n    var dayPeriodEnumValue;\n\n    if (hours >= 17) {\n      dayPeriodEnumValue = dayPeriodEnum.evening;\n    } else if (hours >= 12) {\n      dayPeriodEnumValue = dayPeriodEnum.afternoon;\n    } else if (hours >= 4) {\n      dayPeriodEnumValue = dayPeriodEnum.morning;\n    } else {\n      dayPeriodEnumValue = dayPeriodEnum.night;\n    }\n\n    switch (token) {\n      case 'B':\n      case 'BB':\n      case 'BBB':\n        return localize.dayPeriod(dayPeriodEnumValue, {\n          width: 'abbreviated',\n          context: 'formatting'\n        });\n\n      case 'BBBBB':\n        return localize.dayPeriod(dayPeriodEnumValue, {\n          width: 'narrow',\n          context: 'formatting'\n        });\n\n      case 'BBBB':\n      default:\n        return localize.dayPeriod(dayPeriodEnumValue, {\n          width: 'wide',\n          context: 'formatting'\n        });\n    }\n  },\n  // Hour [1-12]\n  h: function (date, token, localize) {\n    if (token === 'ho') {\n      var hours = date.getUTCHours() % 12;\n      if (hours === 0) hours = 12;\n      return localize.ordinalNumber(hours, {\n        unit: 'hour'\n      });\n    }\n\n    return lightFormatters.h(date, token);\n  },\n  // Hour [0-23]\n  H: function (date, token, localize) {\n    if (token === 'Ho') {\n      return localize.ordinalNumber(date.getUTCHours(), {\n        unit: 'hour'\n      });\n    }\n\n    return lightFormatters.H(date, token);\n  },\n  // Hour [0-11]\n  K: function (date, token, localize) {\n    var hours = date.getUTCHours() % 12;\n\n    if (token === 'Ko') {\n      return localize.ordinalNumber(hours, {\n        unit: 'hour'\n      });\n    }\n\n    return addLeadingZeros(hours, token.length);\n  },\n  // Hour [1-24]\n  k: function (date, token, localize) {\n    var hours = date.getUTCHours();\n    if (hours === 0) hours = 24;\n\n    if (token === 'ko') {\n      return localize.ordinalNumber(hours, {\n        unit: 'hour'\n      });\n    }\n\n    return addLeadingZeros(hours, token.length);\n  },\n  // Minute\n  m: function (date, token, localize) {\n    if (token === 'mo') {\n      return localize.ordinalNumber(date.getUTCMinutes(), {\n        unit: 'minute'\n      });\n    }\n\n    return lightFormatters.m(date, token);\n  },\n  // Second\n  s: function (date, token, localize) {\n    if (token === 'so') {\n      return localize.ordinalNumber(date.getUTCSeconds(), {\n        unit: 'second'\n      });\n    }\n\n    return lightFormatters.s(date, token);\n  },\n  // Fraction of second\n  S: function (date, token) {\n    return lightFormatters.S(date, token);\n  },\n  // Timezone (ISO-8601. If offset is 0, output is always `'Z'`)\n  X: function (date, token, _localize, options) {\n    var originalDate = options._originalDate || date;\n    var timezoneOffset = originalDate.getTimezoneOffset();\n\n    if (timezoneOffset === 0) {\n      return 'Z';\n    }\n\n    switch (token) {\n      // Hours and optional minutes\n      case 'X':\n        return formatTimezoneWithOptionalMinutes(timezoneOffset);\n      // Hours, minutes and optional seconds without `:` delimiter\n      // Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets\n      // so this token always has the same output as `XX`\n\n      case 'XXXX':\n      case 'XX':\n        // Hours and minutes without `:` delimiter\n        return formatTimezone(timezoneOffset);\n      // Hours, minutes and optional seconds with `:` delimiter\n      // Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets\n      // so this token always has the same output as `XXX`\n\n      case 'XXXXX':\n      case 'XXX': // Hours and minutes with `:` delimiter\n\n      default:\n        return formatTimezone(timezoneOffset, ':');\n    }\n  },\n  // Timezone (ISO-8601. If offset is 0, output is `'+00:00'` or equivalent)\n  x: function (date, token, _localize, options) {\n    var originalDate = options._originalDate || date;\n    var timezoneOffset = originalDate.getTimezoneOffset();\n\n    switch (token) {\n      // Hours and optional minutes\n      case 'x':\n        return formatTimezoneWithOptionalMinutes(timezoneOffset);\n      // Hours, minutes and optional seconds without `:` delimiter\n      // Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets\n      // so this token always has the same output as `xx`\n\n      case 'xxxx':\n      case 'xx':\n        // Hours and minutes without `:` delimiter\n        return formatTimezone(timezoneOffset);\n      // Hours, minutes and optional seconds with `:` delimiter\n      // Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets\n      // so this token always has the same output as `xxx`\n\n      case 'xxxxx':\n      case 'xxx': // Hours and minutes with `:` delimiter\n\n      default:\n        return formatTimezone(timezoneOffset, ':');\n    }\n  },\n  // Timezone (GMT)\n  O: function (date, token, _localize, options) {\n    var originalDate = options._originalDate || date;\n    var timezoneOffset = originalDate.getTimezoneOffset();\n\n    switch (token) {\n      // Short\n      case 'O':\n      case 'OO':\n      case 'OOO':\n        return 'GMT' + formatTimezoneShort(timezoneOffset, ':');\n      // Long\n\n      case 'OOOO':\n      default:\n        return 'GMT' + formatTimezone(timezoneOffset, ':');\n    }\n  },\n  // Timezone (specific non-location)\n  z: function (date, token, _localize, options) {\n    var originalDate = options._originalDate || date;\n    var timezoneOffset = originalDate.getTimezoneOffset();\n\n    switch (token) {\n      // Short\n      case 'z':\n      case 'zz':\n      case 'zzz':\n        return 'GMT' + formatTimezoneShort(timezoneOffset, ':');\n      // Long\n\n      case 'zzzz':\n      default:\n        return 'GMT' + formatTimezone(timezoneOffset, ':');\n    }\n  },\n  // Seconds timestamp\n  t: function (date, token, _localize, options) {\n    var originalDate = options._originalDate || date;\n    var timestamp = Math.floor(originalDate.getTime() / 1000);\n    return addLeadingZeros(timestamp, token.length);\n  },\n  // Milliseconds timestamp\n  T: function (date, token, _localize, options) {\n    var originalDate = options._originalDate || date;\n    var timestamp = originalDate.getTime();\n    return addLeadingZeros(timestamp, token.length);\n  }\n};\n\nfunction formatTimezoneShort(offset, dirtyDelimiter) {\n  var sign = offset > 0 ? '-' : '+';\n  var absOffset = Math.abs(offset);\n  var hours = Math.floor(absOffset / 60);\n  var minutes = absOffset % 60;\n\n  if (minutes === 0) {\n    return sign + String(hours);\n  }\n\n  var delimiter = dirtyDelimiter || '';\n  return sign + String(hours) + delimiter + addLeadingZeros(minutes, 2);\n}\n\nfunction formatTimezoneWithOptionalMinutes(offset, dirtyDelimiter) {\n  if (offset % 60 === 0) {\n    var sign = offset > 0 ? '-' : '+';\n    return sign + addLeadingZeros(Math.abs(offset) / 60, 2);\n  }\n\n  return formatTimezone(offset, dirtyDelimiter);\n}\n\nfunction formatTimezone(offset, dirtyDelimiter) {\n  var delimiter = dirtyDelimiter || '';\n  var sign = offset > 0 ? '-' : '+';\n  var absOffset = Math.abs(offset);\n  var hours = addLeadingZeros(Math.floor(absOffset / 60), 2);\n  var minutes = addLeadingZeros(absOffset % 60, 2);\n  return sign + hours + delimiter + minutes;\n}\n\nexport default formatters;", "function dateLongFormatter(pattern, formatLong) {\n  switch (pattern) {\n    case 'P':\n      return formatLong.date({\n        width: 'short'\n      });\n\n    case 'PP':\n      return formatLong.date({\n        width: 'medium'\n      });\n\n    case 'PPP':\n      return formatLong.date({\n        width: 'long'\n      });\n\n    case 'PPPP':\n    default:\n      return formatLong.date({\n        width: 'full'\n      });\n  }\n}\n\nfunction timeLongFormatter(pattern, formatLong) {\n  switch (pattern) {\n    case 'p':\n      return formatLong.time({\n        width: 'short'\n      });\n\n    case 'pp':\n      return formatLong.time({\n        width: 'medium'\n      });\n\n    case 'ppp':\n      return formatLong.time({\n        width: 'long'\n      });\n\n    case 'pppp':\n    default:\n      return formatLong.time({\n        width: 'full'\n      });\n  }\n}\n\nfunction dateTimeLongFormatter(pattern, formatLong) {\n  var matchResult = pattern.match(/(P+)(p+)?/);\n  var datePattern = matchResult[1];\n  var timePattern = matchResult[2];\n\n  if (!timePattern) {\n    return dateLongFormatter(pattern, formatLong);\n  }\n\n  var dateTimeFormat;\n\n  switch (datePattern) {\n    case 'P':\n      dateTimeFormat = formatLong.dateTime({\n        width: 'short'\n      });\n      break;\n\n    case 'PP':\n      dateTimeFormat = formatLong.dateTime({\n        width: 'medium'\n      });\n      break;\n\n    case 'PPP':\n      dateTimeFormat = formatLong.dateTime({\n        width: 'long'\n      });\n      break;\n\n    case 'PPPP':\n    default:\n      dateTimeFormat = formatLong.dateTime({\n        width: 'full'\n      });\n      break;\n  }\n\n  return dateTimeFormat.replace('{{date}}', dateLongFormatter(datePattern, formatLong)).replace('{{time}}', timeLongFormatter(timePattern, formatLong));\n}\n\nvar longFormatters = {\n  p: timeLongFormatter,\n  P: dateTimeLongFormatter\n};\nexport default longFormatters;", "var protectedDayOfYearTokens = ['D', 'DD'];\nvar protectedWeekYearTokens = ['YY', 'YYYY'];\nexport function isProtectedDayOfYearToken(token) {\n  return protectedDayOfYearTokens.indexOf(token) !== -1;\n}\nexport function isProtectedWeekYearToken(token) {\n  return protectedWeekYearTokens.indexOf(token) !== -1;\n}\nexport function throwProtectedError(token, format, input) {\n  if (token === 'YYYY') {\n    throw new RangeError(\"Use `yyyy` instead of `YYYY` (in `\".concat(format, \"`) for formatting years to the input `\").concat(input, \"`; see: https://git.io/fxCyr\"));\n  } else if (token === 'YY') {\n    throw new RangeError(\"Use `yy` instead of `YY` (in `\".concat(format, \"`) for formatting years to the input `\").concat(input, \"`; see: https://git.io/fxCyr\"));\n  } else if (token === 'D') {\n    throw new RangeError(\"Use `d` instead of `D` (in `\".concat(format, \"`) for formatting days of the month to the input `\").concat(input, \"`; see: https://git.io/fxCyr\"));\n  } else if (token === 'DD') {\n    throw new RangeError(\"Use `dd` instead of `DD` (in `\".concat(format, \"`) for formatting days of the month to the input `\").concat(input, \"`; see: https://git.io/fxCyr\"));\n  }\n}", "import isValid from \"../isValid/index.js\";\nimport defaultLocale from \"../locale/en-US/index.js\";\nimport subMilliseconds from \"../subMilliseconds/index.js\";\nimport toDate from \"../toDate/index.js\";\nimport formatters from \"../_lib/format/formatters/index.js\";\nimport longFormatters from \"../_lib/format/longFormatters/index.js\";\nimport getTimezoneOffsetInMilliseconds from \"../_lib/getTimezoneOffsetInMilliseconds/index.js\";\nimport { isProtectedDayOfYearToken, isProtectedWeekYearToken, throwProtectedError } from \"../_lib/protectedTokens/index.js\";\nimport toInteger from \"../_lib/toInteger/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\"; // This RegExp consists of three parts separated by `|`:\n// - [yYQqMLwIdDecihHKkms]o matches any available ordinal number token\n//   (one of the certain letters followed by `o`)\n// - (\\w)\\1* matches any sequences of the same letter\n// - '' matches two quote characters in a row\n// - '(''|[^'])+('|$) matches anything surrounded by two quote characters ('),\n//   except a single quote symbol, which ends the sequence.\n//   Two quote characters do not end the sequence.\n//   If there is no matching single quote\n//   then the sequence will continue until the end of the string.\n// - . matches any single character unmatched by previous parts of the RegExps\n\nvar formattingTokensRegExp = /[yYQqMLwIdDecihHKkms]o|(\\w)\\1*|''|'(''|[^'])+('|$)|./g; // This RegExp catches symbols escaped by quotes, and also\n// sequences of symbols P, p, and the combinations like `PPPPPPPppppp`\n\nvar longFormattingTokensRegExp = /P+p+|P+|p+|''|'(''|[^'])+('|$)|./g;\nvar escapedStringRegExp = /^'([^]*?)'?$/;\nvar doubleQuoteRegExp = /''/g;\nvar unescapedLatinCharacterRegExp = /[a-zA-Z]/;\n/**\n * @name format\n * @category Common Helpers\n * @summary Format the date.\n *\n * @description\n * Return the formatted date string in the given format. The result may vary by locale.\n *\n * > \u26A0\uFE0F Please note that the `format` tokens differ from Moment.js and other libraries.\n * > See: https://git.io/fxCyr\n *\n * The characters wrapped between two single quotes characters (') are escaped.\n * Two single quotes in a row, whether inside or outside a quoted sequence, represent a 'real' single quote.\n * (see the last example)\n *\n * Format of the string is based on Unicode Technical Standard #35:\n * https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table\n * with a few additions (see note 7 below the table).\n *\n * Accepted patterns:\n * | Unit                            | Pattern | Result examples                   | Notes |\n * |---------------------------------|---------|-----------------------------------|-------|\n * | Era                             | G..GGG  | AD, BC                            |       |\n * |                                 | GGGG    | Anno Domini, Before Christ        | 2     |\n * |                                 | GGGGG   | A, B                              |       |\n * | Calendar year                   | y       | 44, 1, 1900, 2017                 | 5     |\n * |                                 | yo      | 44th, 1st, 0th, 17th              | 5,7   |\n * |                                 | yy      | 44, 01, 00, 17                    | 5     |\n * |                                 | yyy     | 044, 001, 1900, 2017              | 5     |\n * |                                 | yyyy    | 0044, 0001, 1900, 2017            | 5     |\n * |                                 | yyyyy   | ...                               | 3,5   |\n * | Local week-numbering year       | Y       | 44, 1, 1900, 2017                 | 5     |\n * |                                 | Yo      | 44th, 1st, 1900th, 2017th         | 5,7   |\n * |                                 | YY      | 44, 01, 00, 17                    | 5,8   |\n * |                                 | YYY     | 044, 001, 1900, 2017              | 5     |\n * |                                 | YYYY    | 0044, 0001, 1900, 2017            | 5,8   |\n * |                                 | YYYYY   | ...                               | 3,5   |\n * | ISO week-numbering year         | R       | -43, 0, 1, 1900, 2017             | 5,7   |\n * |                                 | RR      | -43, 00, 01, 1900, 2017           | 5,7   |\n * |                                 | RRR     | -043, 000, 001, 1900, 2017        | 5,7   |\n * |                                 | RRRR    | -0043, 0000, 0001, 1900, 2017     | 5,7   |\n * |                                 | RRRRR   | ...                               | 3,5,7 |\n * | Extended year                   | u       | -43, 0, 1, 1900, 2017             | 5     |\n * |                                 | uu      | -43, 01, 1900, 2017               | 5     |\n * |                                 | uuu     | -043, 001, 1900, 2017             | 5     |\n * |                                 | uuuu    | -0043, 0001, 1900, 2017           | 5     |\n * |                                 | uuuuu   | ...                               | 3,5   |\n * | Quarter (formatting)            | Q       | 1, 2, 3, 4                        |       |\n * |                                 | Qo      | 1st, 2nd, 3rd, 4th                | 7     |\n * |                                 | QQ      | 01, 02, 03, 04                    |       |\n * |                                 | QQQ     | Q1, Q2, Q3, Q4                    |       |\n * |                                 | QQQQ    | 1st quarter, 2nd quarter, ...     | 2     |\n * |                                 | QQQQQ   | 1, 2, 3, 4                        | 4     |\n * | Quarter (stand-alone)           | q       | 1, 2, 3, 4                        |       |\n * |                                 | qo      | 1st, 2nd, 3rd, 4th                | 7     |\n * |                                 | qq      | 01, 02, 03, 04                    |       |\n * |                                 | qqq     | Q1, Q2, Q3, Q4                    |       |\n * |                                 | qqqq    | 1st quarter, 2nd quarter, ...     | 2     |\n * |                                 | qqqqq   | 1, 2, 3, 4                        | 4     |\n * | Month (formatting)              | M       | 1, 2, ..., 12                     |       |\n * |                                 | Mo      | 1st, 2nd, ..., 12th               | 7     |\n * |                                 | MM      | 01, 02, ..., 12                   |       |\n * |                                 | MMM     | Jan, Feb, ..., Dec                |       |\n * |                                 | MMMM    | January, February, ..., December  | 2     |\n * |                                 | MMMMM   | J, F, ..., D                      |       |\n * | Month (stand-alone)             | L       | 1, 2, ..., 12                     |       |\n * |                                 | Lo      | 1st, 2nd, ..., 12th               | 7     |\n * |                                 | LL      | 01, 02, ..., 12                   |       |\n * |                                 | LLL     | Jan, Feb, ..., Dec                |       |\n * |                                 | LLLL    | January, February, ..., December  | 2     |\n * |                                 | LLLLL   | J, F, ..., D                      |       |\n * | Local week of year              | w       | 1, 2, ..., 53                     |       |\n * |                                 | wo      | 1st, 2nd, ..., 53th               | 7     |\n * |                                 | ww      | 01, 02, ..., 53                   |       |\n * | ISO week of year                | I       | 1, 2, ..., 53                     | 7     |\n * |                                 | Io      | 1st, 2nd, ..., 53th               | 7     |\n * |                                 | II      | 01, 02, ..., 53                   | 7     |\n * | Day of month                    | d       | 1, 2, ..., 31                     |       |\n * |                                 | do      | 1st, 2nd, ..., 31st               | 7     |\n * |                                 | dd      | 01, 02, ..., 31                   |       |\n * | Day of year                     | D       | 1, 2, ..., 365, 366               | 9     |\n * |                                 | Do      | 1st, 2nd, ..., 365th, 366th       | 7     |\n * |                                 | DD      | 01, 02, ..., 365, 366             | 9     |\n * |                                 | DDD     | 001, 002, ..., 365, 366           |       |\n * |                                 | DDDD    | ...                               | 3     |\n * | Day of week (formatting)        | E..EEE  | Mon, Tue, Wed, ..., Sun           |       |\n * |                                 | EEEE    | Monday, Tuesday, ..., Sunday      | 2     |\n * |                                 | EEEEE   | M, T, W, T, F, S, S               |       |\n * |                                 | EEEEEE  | Mo, Tu, We, Th, Fr, Su, Sa        |       |\n * | ISO day of week (formatting)    | i       | 1, 2, 3, ..., 7                   | 7     |\n * |                                 | io      | 1st, 2nd, ..., 7th                | 7     |\n * |                                 | ii      | 01, 02, ..., 07                   | 7     |\n * |                                 | iii     | Mon, Tue, Wed, ..., Sun           | 7     |\n * |                                 | iiii    | Monday, Tuesday, ..., Sunday      | 2,7   |\n * |                                 | iiiii   | M, T, W, T, F, S, S               | 7     |\n * |                                 | iiiiii  | Mo, Tu, We, Th, Fr, Su, Sa        | 7     |\n * | Local day of week (formatting)  | e       | 2, 3, 4, ..., 1                   |       |\n * |                                 | eo      | 2nd, 3rd, ..., 1st                | 7     |\n * |                                 | ee      | 02, 03, ..., 01                   |       |\n * |                                 | eee     | Mon, Tue, Wed, ..., Sun           |       |\n * |                                 | eeee    | Monday, Tuesday, ..., Sunday      | 2     |\n * |                                 | eeeee   | M, T, W, T, F, S, S               |       |\n * |                                 | eeeeee  | Mo, Tu, We, Th, Fr, Su, Sa        |       |\n * | Local day of week (stand-alone) | c       | 2, 3, 4, ..., 1                   |       |\n * |                                 | co      | 2nd, 3rd, ..., 1st                | 7     |\n * |                                 | cc      | 02, 03, ..., 01                   |       |\n * |                                 | ccc     | Mon, Tue, Wed, ..., Sun           |       |\n * |                                 | cccc    | Monday, Tuesday, ..., Sunday      | 2     |\n * |                                 | ccccc   | M, T, W, T, F, S, S               |       |\n * |                                 | cccccc  | Mo, Tu, We, Th, Fr, Su, Sa        |       |\n * | AM, PM                          | a..aa   | AM, PM                            |       |\n * |                                 | aaa     | am, pm                            |       |\n * |                                 | aaaa    | a.m., p.m.                        | 2     |\n * |                                 | aaaaa   | a, p                              |       |\n * | AM, PM, noon, midnight          | b..bb   | AM, PM, noon, midnight            |       |\n * |                                 | bbb     | am, pm, noon, midnight            |       |\n * |                                 | bbbb    | a.m., p.m., noon, midnight        | 2     |\n * |                                 | bbbbb   | a, p, n, mi                       |       |\n * | Flexible day period             | B..BBB  | at night, in the morning, ...     |       |\n * |                                 | BBBB    | at night, in the morning, ...     | 2     |\n * |                                 | BBBBB   | at night, in the morning, ...     |       |\n * | Hour [1-12]                     | h       | 1, 2, ..., 11, 12                 |       |\n * |                                 | ho      | 1st, 2nd, ..., 11th, 12th         | 7     |\n * |                                 | hh      | 01, 02, ..., 11, 12               |       |\n * | Hour [0-23]                     | H       | 0, 1, 2, ..., 23                  |       |\n * |                                 | Ho      | 0th, 1st, 2nd, ..., 23rd          | 7     |\n * |                                 | HH      | 00, 01, 02, ..., 23               |       |\n * | Hour [0-11]                     | K       | 1, 2, ..., 11, 0                  |       |\n * |                                 | Ko      | 1st, 2nd, ..., 11th, 0th          | 7     |\n * |                                 | KK      | 01, 02, ..., 11, 00               |       |\n * | Hour [1-24]                     | k       | 24, 1, 2, ..., 23                 |       |\n * |                                 | ko      | 24th, 1st, 2nd, ..., 23rd         | 7     |\n * |                                 | kk      | 24, 01, 02, ..., 23               |       |\n * | Minute                          | m       | 0, 1, ..., 59                     |       |\n * |                                 | mo      | 0th, 1st, ..., 59th               | 7     |\n * |                                 | mm      | 00, 01, ..., 59                   |       |\n * | Second                          | s       | 0, 1, ..., 59                     |       |\n * |                                 | so      | 0th, 1st, ..., 59th               | 7     |\n * |                                 | ss      | 00, 01, ..., 59                   |       |\n * | Fraction of second              | S       | 0, 1, ..., 9                      |       |\n * |                                 | SS      | 00, 01, ..., 99                   |       |\n * |                                 | SSS     | 000, 001, ..., 999                |       |\n * |                                 | SSSS    | ...                               | 3     |\n * | Timezone (ISO-8601 w/ Z)        | X       | -08, +0530, Z                     |       |\n * |                                 | XX      | -0800, +0530, Z                   |       |\n * |                                 | XXX     | -08:00, +05:30, Z                 |       |\n * |                                 | XXXX    | -0800, +0530, Z, +123456          | 2     |\n * |                                 | XXXXX   | -08:00, +05:30, Z, +12:34:56      |       |\n * | Timezone (ISO-8601 w/o Z)       | x       | -08, +0530, +00                   |       |\n * |                                 | xx      | -0800, +0530, +0000               |       |\n * |                                 | xxx     | -08:00, +05:30, +00:00            | 2     |\n * |                                 | xxxx    | -0800, +0530, +0000, +123456      |       |\n * |                                 | xxxxx   | -08:00, +05:30, +00:00, +12:34:56 |       |\n * | Timezone (GMT)                  | O...OOO | GMT-8, GMT+5:30, GMT+0            |       |\n * |                                 | OOOO    | GMT-08:00, GMT+05:30, GMT+00:00   | 2     |\n * | Timezone (specific non-locat.)  | z...zzz | GMT-8, GMT+5:30, GMT+0            | 6     |\n * |                                 | zzzz    | GMT-08:00, GMT+05:30, GMT+00:00   | 2,6   |\n * | Seconds timestamp               | t       | 512969520                         | 7     |\n * |                                 | tt      | ...                               | 3,7   |\n * | Milliseconds timestamp          | T       | 512969520900                      | 7     |\n * |                                 | TT      | ...                               | 3,7   |\n * | Long localized date             | P       | 04/29/1453                        | 7     |\n * |                                 | PP      | Apr 29, 1453                      | 7     |\n * |                                 | PPP     | April 29th, 1453                  | 7     |\n * |                                 | PPPP    | Friday, April 29th, 1453          | 2,7   |\n * | Long localized time             | p       | 12:00 AM                          | 7     |\n * |                                 | pp      | 12:00:00 AM                       | 7     |\n * |                                 | ppp     | 12:00:00 AM GMT+2                 | 7     |\n * |                                 | pppp    | 12:00:00 AM GMT+02:00             | 2,7   |\n * | Combination of date and time    | Pp      | 04/29/1453, 12:00 AM              | 7     |\n * |                                 | PPpp    | Apr 29, 1453, 12:00:00 AM         | 7     |\n * |                                 | PPPppp  | April 29th, 1453 at ...           | 7     |\n * |                                 | PPPPpppp| Friday, April 29th, 1453 at ...   | 2,7   |\n * Notes:\n * 1. \"Formatting\" units (e.g. formatting quarter) in the default en-US locale\n *    are the same as \"stand-alone\" units, but are different in some languages.\n *    \"Formatting\" units are declined according to the rules of the language\n *    in the context of a date. \"Stand-alone\" units are always nominative singular:\n *\n *    `format(new Date(2017, 10, 6), 'do LLLL', {locale: cs}) //=> '6. listopad'`\n *\n *    `format(new Date(2017, 10, 6), 'do MMMM', {locale: cs}) //=> '6. listopadu'`\n *\n * 2. Any sequence of the identical letters is a pattern, unless it is escaped by\n *    the single quote characters (see below).\n *    If the sequence is longer than listed in table (e.g. `EEEEEEEEEEE`)\n *    the output will be the same as default pattern for this unit, usually\n *    the longest one (in case of ISO weekdays, `EEEE`). Default patterns for units\n *    are marked with \"2\" in the last column of the table.\n *\n *    `format(new Date(2017, 10, 6), 'MMM') //=> 'Nov'`\n *\n *    `format(new Date(2017, 10, 6), 'MMMM') //=> 'November'`\n *\n *    `format(new Date(2017, 10, 6), 'MMMMM') //=> 'N'`\n *\n *    `format(new Date(2017, 10, 6), 'MMMMMM') //=> 'November'`\n *\n *    `format(new Date(2017, 10, 6), 'MMMMMMM') //=> 'November'`\n *\n * 3. Some patterns could be unlimited length (such as `yyyyyyyy`).\n *    The output will be padded with zeros to match the length of the pattern.\n *\n *    `format(new Date(2017, 10, 6), 'yyyyyyyy') //=> '00002017'`\n *\n * 4. `QQQQQ` and `qqqqq` could be not strictly numerical in some locales.\n *    These tokens represent the shortest form of the quarter.\n *\n * 5. The main difference between `y` and `u` patterns are B.C. years:\n *\n *    | Year | `y` | `u` |\n *    |------|-----|-----|\n *    | AC 1 |   1 |   1 |\n *    | BC 1 |   1 |   0 |\n *    | BC 2 |   2 |  -1 |\n *\n *    Also `yy` always returns the last two digits of a year,\n *    while `uu` pads single digit years to 2 characters and returns other years unchanged:\n *\n *    | Year | `yy` | `uu` |\n *    |------|------|------|\n *    | 1    |   01 |   01 |\n *    | 14   |   14 |   14 |\n *    | 376  |   76 |  376 |\n *    | 1453 |   53 | 1453 |\n *\n *    The same difference is true for local and ISO week-numbering years (`Y` and `R`),\n *    except local week-numbering years are dependent on `options.weekStartsOn`\n *    and `options.firstWeekContainsDate` (compare [getISOWeekYear]{@link https://date-fns.org/docs/getISOWeekYear}\n *    and [getWeekYear]{@link https://date-fns.org/docs/getWeekYear}).\n *\n * 6. Specific non-location timezones are currently unavailable in `date-fns`,\n *    so right now these tokens fall back to GMT timezones.\n *\n * 7. These patterns are not in the Unicode Technical Standard #35:\n *    - `i`: ISO day of week\n *    - `I`: ISO week of year\n *    - `R`: ISO week-numbering year\n *    - `t`: seconds timestamp\n *    - `T`: milliseconds timestamp\n *    - `o`: ordinal number modifier\n *    - `P`: long localized date\n *    - `p`: long localized time\n *\n * 8. `YY` and `YYYY` tokens represent week-numbering years but they are often confused with years.\n *    You should enable `options.useAdditionalWeekYearTokens` to use them. See: https://git.io/fxCyr\n *\n * 9. `D` and `DD` tokens represent days of the year but they are ofthen confused with days of the month.\n *    You should enable `options.useAdditionalDayOfYearTokens` to use them. See: https://git.io/fxCyr\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * - The second argument is now required for the sake of explicitness.\n *\n *   ```javascript\n *   // Before v2.0.0\n *   format(new Date(2016, 0, 1))\n *\n *   // v2.0.0 onward\n *   format(new Date(2016, 0, 1), \"yyyy-MM-dd'T'HH:mm:ss.SSSxxx\")\n *   ```\n *\n * - New format string API for `format` function\n *   which is based on [Unicode Technical Standard #35](https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table).\n *   See [this post](https://blog.date-fns.org/post/unicode-tokens-in-date-fns-v2-sreatyki91jg) for more details.\n *\n * - Characters are now escaped using single quote symbols (`'`) instead of square brackets.\n *\n * @param {Date|Number} date - the original date\n * @param {String} format - the string of tokens\n * @param {Object} [options] - an object with options.\n * @param {Locale} [options.locale=defaultLocale] - the locale object. See [Locale]{@link https://date-fns.org/docs/Locale}\n * @param {0|1|2|3|4|5|6} [options.weekStartsOn=0] - the index of the first day of the week (0 - Sunday)\n * @param {Number} [options.firstWeekContainsDate=1] - the day of January, which is\n * @param {Boolean} [options.useAdditionalWeekYearTokens=false] - if true, allows usage of the week-numbering year tokens `YY` and `YYYY`;\n *   see: https://git.io/fxCyr\n * @param {Boolean} [options.useAdditionalDayOfYearTokens=false] - if true, allows usage of the day of year tokens `D` and `DD`;\n *   see: https://git.io/fxCyr\n * @returns {String} the formatted date string\n * @throws {TypeError} 2 arguments required\n * @throws {RangeError} `date` must not be Invalid Date\n * @throws {RangeError} `options.locale` must contain `localize` property\n * @throws {RangeError} `options.locale` must contain `formatLong` property\n * @throws {RangeError} `options.weekStartsOn` must be between 0 and 6\n * @throws {RangeError} `options.firstWeekContainsDate` must be between 1 and 7\n * @throws {RangeError} use `yyyy` instead of `YYYY` for formatting years using [format provided] to the input [input provided]; see: https://git.io/fxCyr\n * @throws {RangeError} use `yy` instead of `YY` for formatting years using [format provided] to the input [input provided]; see: https://git.io/fxCyr\n * @throws {RangeError} use `d` instead of `D` for formatting days of the month using [format provided] to the input [input provided]; see: https://git.io/fxCyr\n * @throws {RangeError} use `dd` instead of `DD` for formatting days of the month using [format provided] to the input [input provided]; see: https://git.io/fxCyr\n * @throws {RangeError} format string contains an unescaped latin alphabet character\n *\n * @example\n * // Represent 11 February 2014 in middle-endian format:\n * var result = format(new Date(2014, 1, 11), 'MM/dd/yyyy')\n * //=> '02/11/2014'\n *\n * @example\n * // Represent 2 July 2014 in Esperanto:\n * import { eoLocale } from 'date-fns/locale/eo'\n * var result = format(new Date(2014, 6, 2), \"do 'de' MMMM yyyy\", {\n *   locale: eoLocale\n * })\n * //=> '2-a de julio 2014'\n *\n * @example\n * // Escape string by single quote characters:\n * var result = format(new Date(2014, 6, 2, 15), \"h 'o''clock'\")\n * //=> \"3 o'clock\"\n */\n\nexport default function format(dirtyDate, dirtyFormatStr, dirtyOptions) {\n  requiredArgs(2, arguments);\n  var formatStr = String(dirtyFormatStr);\n  var options = dirtyOptions || {};\n  var locale = options.locale || defaultLocale;\n  var localeFirstWeekContainsDate = locale.options && locale.options.firstWeekContainsDate;\n  var defaultFirstWeekContainsDate = localeFirstWeekContainsDate == null ? 1 : toInteger(localeFirstWeekContainsDate);\n  var firstWeekContainsDate = options.firstWeekContainsDate == null ? defaultFirstWeekContainsDate : toInteger(options.firstWeekContainsDate); // Test if weekStartsOn is between 1 and 7 _and_ is not NaN\n\n  if (!(firstWeekContainsDate >= 1 && firstWeekContainsDate <= 7)) {\n    throw new RangeError('firstWeekContainsDate must be between 1 and 7 inclusively');\n  }\n\n  var localeWeekStartsOn = locale.options && locale.options.weekStartsOn;\n  var defaultWeekStartsOn = localeWeekStartsOn == null ? 0 : toInteger(localeWeekStartsOn);\n  var weekStartsOn = options.weekStartsOn == null ? defaultWeekStartsOn : toInteger(options.weekStartsOn); // Test if weekStartsOn is between 0 and 6 _and_ is not NaN\n\n  if (!(weekStartsOn >= 0 && weekStartsOn <= 6)) {\n    throw new RangeError('weekStartsOn must be between 0 and 6 inclusively');\n  }\n\n  if (!locale.localize) {\n    throw new RangeError('locale must contain localize property');\n  }\n\n  if (!locale.formatLong) {\n    throw new RangeError('locale must contain formatLong property');\n  }\n\n  var originalDate = toDate(dirtyDate);\n\n  if (!isValid(originalDate)) {\n    throw new RangeError('Invalid time value');\n  } // Convert the date in system timezone to the same date in UTC+00:00 timezone.\n  // This ensures that when UTC functions will be implemented, locales will be compatible with them.\n  // See an issue about UTC functions: https://github.com/date-fns/date-fns/issues/376\n\n\n  var timezoneOffset = getTimezoneOffsetInMilliseconds(originalDate);\n  var utcDate = subMilliseconds(originalDate, timezoneOffset);\n  var formatterOptions = {\n    firstWeekContainsDate: firstWeekContainsDate,\n    weekStartsOn: weekStartsOn,\n    locale: locale,\n    _originalDate: originalDate\n  };\n  var result = formatStr.match(longFormattingTokensRegExp).map(function (substring) {\n    var firstCharacter = substring[0];\n\n    if (firstCharacter === 'p' || firstCharacter === 'P') {\n      var longFormatter = longFormatters[firstCharacter];\n      return longFormatter(substring, locale.formatLong, formatterOptions);\n    }\n\n    return substring;\n  }).join('').match(formattingTokensRegExp).map(function (substring) {\n    // Replace two single quote characters with one single quote character\n    if (substring === \"''\") {\n      return \"'\";\n    }\n\n    var firstCharacter = substring[0];\n\n    if (firstCharacter === \"'\") {\n      return cleanEscapedString(substring);\n    }\n\n    var formatter = formatters[firstCharacter];\n\n    if (formatter) {\n      if (!options.useAdditionalWeekYearTokens && isProtectedWeekYearToken(substring)) {\n        throwProtectedError(substring, dirtyFormatStr, dirtyDate);\n      }\n\n      if (!options.useAdditionalDayOfYearTokens && isProtectedDayOfYearToken(substring)) {\n        throwProtectedError(substring, dirtyFormatStr, dirtyDate);\n      }\n\n      return formatter(utcDate, substring, locale.localize, formatterOptions);\n    }\n\n    if (firstCharacter.match(unescapedLatinCharacterRegExp)) {\n      throw new RangeError('Format string contains an unescaped latin alphabet character `' + firstCharacter + '`');\n    }\n\n    return substring;\n  }).join('');\n  return result;\n}\n\nfunction cleanEscapedString(input) {\n  return input.match(escapedStringRegExp)[1].replace(doubleQuoteRegExp, \"'\");\n}", "export default function assign(target, dirtyObject) {\n  if (target == null) {\n    throw new TypeError('assign requires that input parameter not be null or undefined');\n  }\n\n  dirtyObject = dirtyObject || {};\n\n  for (var property in dirtyObject) {\n    if (Object.prototype.hasOwnProperty.call(dirtyObject, property)) {\n      target[property] = dirtyObject[property];\n    }\n  }\n\n  return target;\n}", "import assign from \"../assign/index.js\";\nexport default function cloneObject(dirtyObject) {\n  return assign({}, dirtyObject);\n}", "import toInteger from \"../_lib/toInteger/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\nvar MILLISECONDS_IN_HOUR = 3600000;\nvar MILLISECONDS_IN_MINUTE = 60000;\nvar DEFAULT_ADDITIONAL_DIGITS = 2;\nvar patterns = {\n  dateTimeDelimiter: /[T ]/,\n  timeZoneDelimiter: /[Z ]/i,\n  timezone: /([Z+-].*)$/\n};\nvar dateRegex = /^-?(?:(\\d{3})|(\\d{2})(?:-?(\\d{2}))?|W(\\d{2})(?:-?(\\d{1}))?|)$/;\nvar timeRegex = /^(\\d{2}(?:[.,]\\d*)?)(?::?(\\d{2}(?:[.,]\\d*)?))?(?::?(\\d{2}(?:[.,]\\d*)?))?$/;\nvar timezoneRegex = /^([+-])(\\d{2})(?::?(\\d{2}))?$/;\n/**\n * @name parseISO\n * @category Common Helpers\n * @summary Parse ISO string\n *\n * @description\n * Parse the given string in ISO 8601 format and return an instance of Date.\n *\n * Function accepts complete ISO 8601 formats as well as partial implementations.\n * ISO 8601: http://en.wikipedia.org/wiki/ISO_8601\n *\n * If the argument isn't a string, the function cannot parse the string or\n * the values are invalid, it returns Invalid Date.\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * - The previous `parse` implementation was renamed to `parseISO`.\n *\n *   ```javascript\n *   // Before v2.0.0\n *   parse('2016-01-01')\n *\n *   // v2.0.0 onward\n *   parseISO('2016-01-01')\n *   ```\n *\n * - `parseISO` now validates separate date and time values in ISO-8601 strings\n *   and returns `Invalid Date` if the date is invalid.\n *\n *   ```javascript\n *   parseISO('2018-13-32')\n *   //=> Invalid Date\n *   ```\n *\n * - `parseISO` now doesn't fall back to `new Date` constructor\n *   if it fails to parse a string argument. Instead, it returns `Invalid Date`.\n *\n * @param {String} argument - the value to convert\n * @param {Object} [options] - an object with options.\n * @param {0|1|2} [options.additionalDigits=2] - the additional number of digits in the extended year format\n * @returns {Date} the parsed date in the local time zone\n * @throws {TypeError} 1 argument required\n * @throws {RangeError} `options.additionalDigits` must be 0, 1 or 2\n *\n * @example\n * // Convert string '2014-02-11T11:30:30' to date:\n * var result = parseISO('2014-02-11T11:30:30')\n * //=> Tue Feb 11 2014 11:30:30\n *\n * @example\n * // Convert string '+02014101' to date,\n * // if the additional number of digits in the extended year format is 1:\n * var result = parseISO('+02014101', { additionalDigits: 1 })\n * //=> Fri Apr 11 2014 00:00:00\n */\n\nexport default function parseISO(argument, dirtyOptions) {\n  requiredArgs(1, arguments);\n  var options = dirtyOptions || {};\n  var additionalDigits = options.additionalDigits == null ? DEFAULT_ADDITIONAL_DIGITS : toInteger(options.additionalDigits);\n\n  if (additionalDigits !== 2 && additionalDigits !== 1 && additionalDigits !== 0) {\n    throw new RangeError('additionalDigits must be 0, 1 or 2');\n  }\n\n  if (!(typeof argument === 'string' || Object.prototype.toString.call(argument) === '[object String]')) {\n    return new Date(NaN);\n  }\n\n  var dateStrings = splitDateString(argument);\n  var date;\n\n  if (dateStrings.date) {\n    var parseYearResult = parseYear(dateStrings.date, additionalDigits);\n    date = parseDate(parseYearResult.restDateString, parseYearResult.year);\n  }\n\n  if (isNaN(date) || !date) {\n    return new Date(NaN);\n  }\n\n  var timestamp = date.getTime();\n  var time = 0;\n  var offset;\n\n  if (dateStrings.time) {\n    time = parseTime(dateStrings.time);\n\n    if (isNaN(time) || time === null) {\n      return new Date(NaN);\n    }\n  }\n\n  if (dateStrings.timezone) {\n    offset = parseTimezone(dateStrings.timezone);\n\n    if (isNaN(offset)) {\n      return new Date(NaN);\n    }\n  } else {\n    var dirtyDate = new Date(timestamp + time); // js parsed string assuming it's in UTC timezone\n    // but we need it to be parsed in our timezone\n    // so we use utc values to build date in our timezone.\n    // Year values from 0 to 99 map to the years 1900 to 1999\n    // so set year explicitly with setFullYear.\n\n    var result = new Date(0);\n    result.setFullYear(dirtyDate.getUTCFullYear(), dirtyDate.getUTCMonth(), dirtyDate.getUTCDate());\n    result.setHours(dirtyDate.getUTCHours(), dirtyDate.getUTCMinutes(), dirtyDate.getUTCSeconds(), dirtyDate.getUTCMilliseconds());\n    return result;\n  }\n\n  return new Date(timestamp + time + offset);\n}\n\nfunction splitDateString(dateString) {\n  var dateStrings = {};\n  var array = dateString.split(patterns.dateTimeDelimiter);\n  var timeString; // The regex match should only return at maximum two array elements.\n  // [date], [time], or [date, time].\n\n  if (array.length > 2) {\n    return dateStrings;\n  }\n\n  if (/:/.test(array[0])) {\n    dateStrings.date = null;\n    timeString = array[0];\n  } else {\n    dateStrings.date = array[0];\n    timeString = array[1];\n\n    if (patterns.timeZoneDelimiter.test(dateStrings.date)) {\n      dateStrings.date = dateString.split(patterns.timeZoneDelimiter)[0];\n      timeString = dateString.substr(dateStrings.date.length, dateString.length);\n    }\n  }\n\n  if (timeString) {\n    var token = patterns.timezone.exec(timeString);\n\n    if (token) {\n      dateStrings.time = timeString.replace(token[1], '');\n      dateStrings.timezone = token[1];\n    } else {\n      dateStrings.time = timeString;\n    }\n  }\n\n  return dateStrings;\n}\n\nfunction parseYear(dateString, additionalDigits) {\n  var regex = new RegExp('^(?:(\\\\d{4}|[+-]\\\\d{' + (4 + additionalDigits) + '})|(\\\\d{2}|[+-]\\\\d{' + (2 + additionalDigits) + '})$)');\n  var captures = dateString.match(regex); // Invalid ISO-formatted year\n\n  if (!captures) return {\n    year: null\n  };\n  var year = captures[1] && parseInt(captures[1]);\n  var century = captures[2] && parseInt(captures[2]);\n  return {\n    year: century == null ? year : century * 100,\n    restDateString: dateString.slice((captures[1] || captures[2]).length)\n  };\n}\n\nfunction parseDate(dateString, year) {\n  // Invalid ISO-formatted year\n  if (year === null) return null;\n  var captures = dateString.match(dateRegex); // Invalid ISO-formatted string\n\n  if (!captures) return null;\n  var isWeekDate = !!captures[4];\n  var dayOfYear = parseDateUnit(captures[1]);\n  var month = parseDateUnit(captures[2]) - 1;\n  var day = parseDateUnit(captures[3]);\n  var week = parseDateUnit(captures[4]);\n  var dayOfWeek = parseDateUnit(captures[5]) - 1;\n\n  if (isWeekDate) {\n    if (!validateWeekDate(year, week, dayOfWeek)) {\n      return new Date(NaN);\n    }\n\n    return dayOfISOWeekYear(year, week, dayOfWeek);\n  } else {\n    var date = new Date(0);\n\n    if (!validateDate(year, month, day) || !validateDayOfYearDate(year, dayOfYear)) {\n      return new Date(NaN);\n    }\n\n    date.setUTCFullYear(year, month, Math.max(dayOfYear, day));\n    return date;\n  }\n}\n\nfunction parseDateUnit(value) {\n  return value ? parseInt(value) : 1;\n}\n\nfunction parseTime(timeString) {\n  var captures = timeString.match(timeRegex);\n  if (!captures) return null; // Invalid ISO-formatted time\n\n  var hours = parseTimeUnit(captures[1]);\n  var minutes = parseTimeUnit(captures[2]);\n  var seconds = parseTimeUnit(captures[3]);\n\n  if (!validateTime(hours, minutes, seconds)) {\n    return NaN;\n  }\n\n  return hours * MILLISECONDS_IN_HOUR + minutes * MILLISECONDS_IN_MINUTE + seconds * 1000;\n}\n\nfunction parseTimeUnit(value) {\n  return value && parseFloat(value.replace(',', '.')) || 0;\n}\n\nfunction parseTimezone(timezoneString) {\n  if (timezoneString === 'Z') return 0;\n  var captures = timezoneString.match(timezoneRegex);\n  if (!captures) return 0;\n  var sign = captures[1] === '+' ? -1 : 1;\n  var hours = parseInt(captures[2]);\n  var minutes = captures[3] && parseInt(captures[3]) || 0;\n\n  if (!validateTimezone(hours, minutes)) {\n    return NaN;\n  }\n\n  return sign * (hours * MILLISECONDS_IN_HOUR + minutes * MILLISECONDS_IN_MINUTE);\n}\n\nfunction dayOfISOWeekYear(isoWeekYear, week, day) {\n  var date = new Date(0);\n  date.setUTCFullYear(isoWeekYear, 0, 4);\n  var fourthOfJanuaryDay = date.getUTCDay() || 7;\n  var diff = (week - 1) * 7 + day + 1 - fourthOfJanuaryDay;\n  date.setUTCDate(date.getUTCDate() + diff);\n  return date;\n} // Validation functions\n// February is null to handle the leap year (using ||)\n\n\nvar daysInMonths = [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\n\nfunction isLeapYearIndex(year) {\n  return year % 400 === 0 || year % 4 === 0 && year % 100;\n}\n\nfunction validateDate(year, month, date) {\n  return month >= 0 && month <= 11 && date >= 1 && date <= (daysInMonths[month] || (isLeapYearIndex(year) ? 29 : 28));\n}\n\nfunction validateDayOfYearDate(year, dayOfYear) {\n  return dayOfYear >= 1 && dayOfYear <= (isLeapYearIndex(year) ? 366 : 365);\n}\n\nfunction validateWeekDate(_year, week, day) {\n  return week >= 1 && week <= 53 && day >= 0 && day <= 6;\n}\n\nfunction validateTime(hours, minutes, seconds) {\n  if (hours === 24) {\n    return minutes === 0 && seconds === 0;\n  }\n\n  return seconds >= 0 && seconds < 60 && minutes >= 0 && minutes < 60 && hours >= 0 && hours < 25;\n}\n\nfunction validateTimezone(_hours, minutes) {\n  return minutes >= 0 && minutes <= 59;\n}", "// wraps value in closure or returns closure\nexport let closure = (value) => {\n  if(typeof value === \"function\"){\n    return value\n  } else {\n    let closure = function (){ return value }\n    return closure\n  }\n}\n", "export const globalSelf = typeof self !== \"undefined\" ? self : null\nexport const phxWindow = typeof window !== \"undefined\" ? window : null\nexport const global = globalSelf || phxWindow || this\nexport const DEFAULT_VSN = \"2.0.0\"\nexport const SOCKET_STATES = {connecting: 0, open: 1, closing: 2, closed: 3}\nexport const DEFAULT_TIMEOUT = 10000\nexport const WS_CLOSE_NORMAL = 1000\nexport const CHANNEL_STATES = {\n  closed: \"closed\",\n  errored: \"errored\",\n  joined: \"joined\",\n  joining: \"joining\",\n  leaving: \"leaving\",\n}\nexport const CHANNEL_EVENTS = {\n  close: \"phx_close\",\n  error: \"phx_error\",\n  join: \"phx_join\",\n  reply: \"phx_reply\",\n  leave: \"phx_leave\"\n}\n\nexport const TRANSPORTS = {\n  longpoll: \"longpoll\",\n  websocket: \"websocket\"\n}\nexport const XHR_STATES = {\n  complete: 4\n}\n", "/**\n * Initializes the Push\n * @param {Channel} channel - The Channel\n * @param {string} event - The event, for example `\"phx_join\"`\n * @param {Object} payload - The payload, for example `{user_id: 123}`\n * @param {number} timeout - The push timeout in milliseconds\n */\nexport default class Push {\n  constructor(channel, event, payload, timeout){\n    this.channel = channel\n    this.event = event\n    this.payload = payload || function (){ return {} }\n    this.receivedResp = null\n    this.timeout = timeout\n    this.timeoutTimer = null\n    this.recHooks = []\n    this.sent = false\n  }\n\n  /**\n   *\n   * @param {number} timeout\n   */\n  resend(timeout){\n    this.timeout = timeout\n    this.reset()\n    this.send()\n  }\n\n  /**\n   *\n   */\n  send(){\n    if(this.hasReceived(\"timeout\")){ return }\n    this.startTimeout()\n    this.sent = true\n    this.channel.socket.push({\n      topic: this.channel.topic,\n      event: this.event,\n      payload: this.payload(),\n      ref: this.ref,\n      join_ref: this.channel.joinRef()\n    })\n  }\n\n  /**\n   *\n   * @param {*} status\n   * @param {*} callback\n   */\n  receive(status, callback){\n    if(this.hasReceived(status)){\n      callback(this.receivedResp.response)\n    }\n\n    this.recHooks.push({status, callback})\n    return this\n  }\n\n  /**\n   * @private\n   */\n  reset(){\n    this.cancelRefEvent()\n    this.ref = null\n    this.refEvent = null\n    this.receivedResp = null\n    this.sent = false\n  }\n\n  /**\n   * @private\n   */\n  matchReceive({status, response, _ref}){\n    this.recHooks.filter(h => h.status === status)\n      .forEach(h => h.callback(response))\n  }\n\n  /**\n   * @private\n   */\n  cancelRefEvent(){\n    if(!this.refEvent){ return }\n    this.channel.off(this.refEvent)\n  }\n\n  /**\n   * @private\n   */\n  cancelTimeout(){\n    clearTimeout(this.timeoutTimer)\n    this.timeoutTimer = null\n  }\n\n  /**\n   * @private\n   */\n  startTimeout(){\n    if(this.timeoutTimer){ this.cancelTimeout() }\n    this.ref = this.channel.socket.makeRef()\n    this.refEvent = this.channel.replyEventName(this.ref)\n\n    this.channel.on(this.refEvent, payload => {\n      this.cancelRefEvent()\n      this.cancelTimeout()\n      this.receivedResp = payload\n      this.matchReceive(payload)\n    })\n\n    this.timeoutTimer = setTimeout(() => {\n      this.trigger(\"timeout\", {})\n    }, this.timeout)\n  }\n\n  /**\n   * @private\n   */\n  hasReceived(status){\n    return this.receivedResp && this.receivedResp.status === status\n  }\n\n  /**\n   * @private\n   */\n  trigger(status, response){\n    this.channel.trigger(this.refEvent, {status, response})\n  }\n}\n", "/**\n *\n * Creates a timer that accepts a `timerCalc` function to perform\n * calculated timeout retries, such as exponential backoff.\n *\n * @example\n * let reconnectTimer = new Timer(() => this.connect(), function(tries){\n *   return [1000, 5000, 10000][tries - 1] || 10000\n * })\n * reconnectTimer.scheduleTimeout() // fires after 1000\n * reconnectTimer.scheduleTimeout() // fires after 5000\n * reconnectTimer.reset()\n * reconnectTimer.scheduleTimeout() // fires after 1000\n *\n * @param {Function} callback\n * @param {Function} timerCalc\n */\nexport default class Timer {\n  constructor(callback, timerCalc){\n    this.callback = callback\n    this.timerCalc = timerCalc\n    this.timer = null\n    this.tries = 0\n  }\n\n  reset(){\n    this.tries = 0\n    clearTimeout(this.timer)\n  }\n\n  /**\n   * Cancels any previous scheduleTimeout and schedules callback\n   */\n  scheduleTimeout(){\n    clearTimeout(this.timer)\n\n    this.timer = setTimeout(() => {\n      this.tries = this.tries + 1\n      this.callback()\n    }, this.timerCalc(this.tries + 1))\n  }\n}\n", "import {closure} from \"./utils\"\nimport {\n  CHANNEL_EVENTS,\n  CHANNEL_STATES,\n} from \"./constants\"\n\nimport Push from \"./push\"\nimport Timer from \"./timer\"\n\n/**\n *\n * @param {string} topic\n * @param {(Object|function)} params\n * @param {Socket} socket\n */\nexport default class Channel {\n  constructor(topic, params, socket){\n    this.state = CHANNEL_STATES.closed\n    this.topic = topic\n    this.params = closure(params || {})\n    this.socket = socket\n    this.bindings = []\n    this.bindingRef = 0\n    this.timeout = this.socket.timeout\n    this.joinedOnce = false\n    this.joinPush = new Push(this, CHANNEL_EVENTS.join, this.params, this.timeout)\n    this.pushBuffer = []\n    this.stateChangeRefs = []\n\n    this.rejoinTimer = new Timer(() => {\n      if(this.socket.isConnected()){ this.rejoin() }\n    }, this.socket.rejoinAfterMs)\n    this.stateChangeRefs.push(this.socket.onError(() => this.rejoinTimer.reset()))\n    this.stateChangeRefs.push(this.socket.onOpen(() => {\n      this.rejoinTimer.reset()\n      if(this.isErrored()){ this.rejoin() }\n    })\n    )\n    this.joinPush.receive(\"ok\", () => {\n      this.state = CHANNEL_STATES.joined\n      this.rejoinTimer.reset()\n      this.pushBuffer.forEach(pushEvent => pushEvent.send())\n      this.pushBuffer = []\n    })\n    this.joinPush.receive(\"error\", () => {\n      this.state = CHANNEL_STATES.errored\n      if(this.socket.isConnected()){ this.rejoinTimer.scheduleTimeout() }\n    })\n    this.onClose(() => {\n      this.rejoinTimer.reset()\n      if(this.socket.hasLogger()) this.socket.log(\"channel\", `close ${this.topic} ${this.joinRef()}`)\n      this.state = CHANNEL_STATES.closed\n      this.socket.remove(this)\n    })\n    this.onError(reason => {\n      if(this.socket.hasLogger()) this.socket.log(\"channel\", `error ${this.topic}`, reason)\n      if(this.isJoining()){ this.joinPush.reset() }\n      this.state = CHANNEL_STATES.errored\n      if(this.socket.isConnected()){ this.rejoinTimer.scheduleTimeout() }\n    })\n    this.joinPush.receive(\"timeout\", () => {\n      if(this.socket.hasLogger()) this.socket.log(\"channel\", `timeout ${this.topic} (${this.joinRef()})`, this.joinPush.timeout)\n      let leavePush = new Push(this, CHANNEL_EVENTS.leave, closure({}), this.timeout)\n      leavePush.send()\n      this.state = CHANNEL_STATES.errored\n      this.joinPush.reset()\n      if(this.socket.isConnected()){ this.rejoinTimer.scheduleTimeout() }\n    })\n    this.on(CHANNEL_EVENTS.reply, (payload, ref) => {\n      this.trigger(this.replyEventName(ref), payload)\n    })\n  }\n\n  /**\n   * Join the channel\n   * @param {integer} timeout\n   * @returns {Push}\n   */\n  join(timeout = this.timeout){\n    if(this.joinedOnce){\n      throw new Error(\"tried to join multiple times. 'join' can only be called a single time per channel instance\")\n    } else {\n      this.timeout = timeout\n      this.joinedOnce = true\n      this.rejoin()\n      return this.joinPush\n    }\n  }\n\n  /**\n   * Hook into channel close\n   * @param {Function} callback\n   */\n  onClose(callback){\n    this.on(CHANNEL_EVENTS.close, callback)\n  }\n\n  /**\n   * Hook into channel errors\n   * @param {Function} callback\n   */\n  onError(callback){\n    return this.on(CHANNEL_EVENTS.error, reason => callback(reason))\n  }\n\n  /**\n   * Subscribes on channel events\n   *\n   * Subscription returns a ref counter, which can be used later to\n   * unsubscribe the exact event listener\n   *\n   * @example\n   * const ref1 = channel.on(\"event\", do_stuff)\n   * const ref2 = channel.on(\"event\", do_other_stuff)\n   * channel.off(\"event\", ref1)\n   * // Since unsubscription, do_stuff won't fire,\n   * // while do_other_stuff will keep firing on the \"event\"\n   *\n   * @param {string} event\n   * @param {Function} callback\n   * @returns {integer} ref\n   */\n  on(event, callback){\n    let ref = this.bindingRef++\n    this.bindings.push({event, ref, callback})\n    return ref\n  }\n\n  /**\n   * Unsubscribes off of channel events\n   *\n   * Use the ref returned from a channel.on() to unsubscribe one\n   * handler, or pass nothing for the ref to unsubscribe all\n   * handlers for the given event.\n   *\n   * @example\n   * // Unsubscribe the do_stuff handler\n   * const ref1 = channel.on(\"event\", do_stuff)\n   * channel.off(\"event\", ref1)\n   *\n   * // Unsubscribe all handlers from event\n   * channel.off(\"event\")\n   *\n   * @param {string} event\n   * @param {integer} ref\n   */\n  off(event, ref){\n    this.bindings = this.bindings.filter((bind) => {\n      return !(bind.event === event && (typeof ref === \"undefined\" || ref === bind.ref))\n    })\n  }\n\n  /**\n   * @private\n   */\n  canPush(){ return this.socket.isConnected() && this.isJoined() }\n\n  /**\n   * Sends a message `event` to phoenix with the payload `payload`.\n   * Phoenix receives this in the `handle_in(event, payload, socket)`\n   * function. if phoenix replies or it times out (default 10000ms),\n   * then optionally the reply can be received.\n   *\n   * @example\n   * channel.push(\"event\")\n   *   .receive(\"ok\", payload => console.log(\"phoenix replied:\", payload))\n   *   .receive(\"error\", err => console.log(\"phoenix errored\", err))\n   *   .receive(\"timeout\", () => console.log(\"timed out pushing\"))\n   * @param {string} event\n   * @param {Object} payload\n   * @param {number} [timeout]\n   * @returns {Push}\n   */\n  push(event, payload, timeout = this.timeout){\n    payload = payload || {}\n    if(!this.joinedOnce){\n      throw new Error(`tried to push '${event}' to '${this.topic}' before joining. Use channel.join() before pushing events`)\n    }\n    let pushEvent = new Push(this, event, function (){ return payload }, timeout)\n    if(this.canPush()){\n      pushEvent.send()\n    } else {\n      pushEvent.startTimeout()\n      this.pushBuffer.push(pushEvent)\n    }\n\n    return pushEvent\n  }\n\n  /** Leaves the channel\n   *\n   * Unsubscribes from server events, and\n   * instructs channel to terminate on server\n   *\n   * Triggers onClose() hooks\n   *\n   * To receive leave acknowledgements, use the `receive`\n   * hook to bind to the server ack, ie:\n   *\n   * @example\n   * channel.leave().receive(\"ok\", () => alert(\"left!\") )\n   *\n   * @param {integer} timeout\n   * @returns {Push}\n   */\n  leave(timeout = this.timeout){\n    this.rejoinTimer.reset()\n    this.joinPush.cancelTimeout()\n\n    this.state = CHANNEL_STATES.leaving\n    let onClose = () => {\n      if(this.socket.hasLogger()) this.socket.log(\"channel\", `leave ${this.topic}`)\n      this.trigger(CHANNEL_EVENTS.close, \"leave\")\n    }\n    let leavePush = new Push(this, CHANNEL_EVENTS.leave, closure({}), timeout)\n    leavePush.receive(\"ok\", () => onClose())\n      .receive(\"timeout\", () => onClose())\n    leavePush.send()\n    if(!this.canPush()){ leavePush.trigger(\"ok\", {}) }\n\n    return leavePush\n  }\n\n  /**\n   * Overridable message hook\n   *\n   * Receives all events for specialized message handling\n   * before dispatching to the channel callbacks.\n   *\n   * Must return the payload, modified or unmodified\n   * @param {string} event\n   * @param {Object} payload\n   * @param {integer} ref\n   * @returns {Object}\n   */\n  onMessage(_event, payload, _ref){ return payload }\n\n  /**\n   * @private\n   */\n  isMember(topic, event, payload, joinRef){\n    if(this.topic !== topic){ return false }\n\n    if(joinRef && joinRef !== this.joinRef()){\n      if(this.socket.hasLogger()) this.socket.log(\"channel\", \"dropping outdated message\", {topic, event, payload, joinRef})\n      return false\n    } else {\n      return true\n    }\n  }\n\n  /**\n   * @private\n   */\n  joinRef(){ return this.joinPush.ref }\n\n  /**\n   * @private\n   */\n  rejoin(timeout = this.timeout){\n    if(this.isLeaving()){ return }\n    this.socket.leaveOpenTopic(this.topic)\n    this.state = CHANNEL_STATES.joining\n    this.joinPush.resend(timeout)\n  }\n\n  /**\n   * @private\n   */\n  trigger(event, payload, ref, joinRef){\n    let handledPayload = this.onMessage(event, payload, ref, joinRef)\n    if(payload && !handledPayload){ throw new Error(\"channel onMessage callbacks must return the payload, modified or unmodified\") }\n\n    let eventBindings = this.bindings.filter(bind => bind.event === event)\n\n    for(let i = 0; i < eventBindings.length; i++){\n      let bind = eventBindings[i]\n      bind.callback(handledPayload, ref, joinRef || this.joinRef())\n    }\n  }\n\n  /**\n   * @private\n   */\n  replyEventName(ref){ return `chan_reply_${ref}` }\n\n  /**\n   * @private\n   */\n  isClosed(){ return this.state === CHANNEL_STATES.closed }\n\n  /**\n   * @private\n   */\n  isErrored(){ return this.state === CHANNEL_STATES.errored }\n\n  /**\n   * @private\n   */\n  isJoined(){ return this.state === CHANNEL_STATES.joined }\n\n  /**\n   * @private\n   */\n  isJoining(){ return this.state === CHANNEL_STATES.joining }\n\n  /**\n   * @private\n   */\n  isLeaving(){ return this.state === CHANNEL_STATES.leaving }\n}\n", "import {\n  global,\n  XHR_STATES\n} from \"./constants\"\n\nexport default class Ajax {\n\n  static request(method, endPoint, accept, body, timeout, ontimeout, callback){\n    if(global.XDomainRequest){\n      let req = new global.XDomainRequest() // IE8, IE9\n      this.xdomainRequest(req, method, endPoint, body, timeout, ontimeout, callback)\n    } else {\n      let req = new global.XMLHttpRequest() // IE7+, Firefox, Chrome, Opera, Safari\n      this.xhrRequest(req, method, endPoint, accept, body, timeout, ontimeout, callback)\n    }\n  }\n\n  static xdomainRequest(req, method, endPoint, body, timeout, ontimeout, callback){\n    req.timeout = timeout\n    req.open(method, endPoint)\n    req.onload = () => {\n      let response = this.parseJSON(req.responseText)\n      callback && callback(response)\n    }\n    if(ontimeout){ req.ontimeout = ontimeout }\n\n    // Work around bug in IE9 that requires an attached onprogress handler\n    req.onprogress = () => { }\n\n    req.send(body)\n  }\n\n  static xhrRequest(req, method, endPoint, accept, body, timeout, ontimeout, callback){\n    req.open(method, endPoint, true)\n    req.timeout = timeout\n    req.setRequestHeader(\"Content-Type\", accept)\n    req.onerror = () => { callback && callback(null) }\n    req.onreadystatechange = () => {\n      if(req.readyState === XHR_STATES.complete && callback){\n        let response = this.parseJSON(req.responseText)\n        callback(response)\n      }\n    }\n    if(ontimeout){ req.ontimeout = ontimeout }\n\n    req.send(body)\n  }\n\n  static parseJSON(resp){\n    if(!resp || resp === \"\"){ return null }\n\n    try {\n      return JSON.parse(resp)\n    } catch (e){\n      console && console.log(\"failed to parse JSON response\", resp)\n      return null\n    }\n  }\n\n  static serialize(obj, parentKey){\n    let queryStr = []\n    for(var key in obj){\n      if(!Object.prototype.hasOwnProperty.call(obj, key)){ continue }\n      let paramKey = parentKey ? `${parentKey}[${key}]` : key\n      let paramVal = obj[key]\n      if(typeof paramVal === \"object\"){\n        queryStr.push(this.serialize(paramVal, paramKey))\n      } else {\n        queryStr.push(encodeURIComponent(paramKey) + \"=\" + encodeURIComponent(paramVal))\n      }\n    }\n    return queryStr.join(\"&\")\n  }\n\n  static appendParams(url, params){\n    if(Object.keys(params).length === 0){ return url }\n\n    let prefix = url.match(/\\?/) ? \"&\" : \"?\"\n    return `${url}${prefix}${this.serialize(params)}`\n  }\n}\n", "import {\n  SOCKET_STATES,\n  TRANSPORTS\n} from \"./constants\"\n\nimport Ajax from \"./ajax\"\n\nexport default class LongPoll {\n\n  constructor(endPoint){\n    this.endPoint = null\n    this.token = null\n    this.skipHeartbeat = true\n    this.onopen = function (){ } // noop\n    this.onerror = function (){ } // noop\n    this.onmessage = function (){ } // noop\n    this.onclose = function (){ } // noop\n    this.pollEndpoint = this.normalizeEndpoint(endPoint)\n    this.readyState = SOCKET_STATES.connecting\n\n    this.poll()\n  }\n\n  normalizeEndpoint(endPoint){\n    return (endPoint\n      .replace(\"ws://\", \"http://\")\n      .replace(\"wss://\", \"https://\")\n      .replace(new RegExp(\"(.*)\\/\" + TRANSPORTS.websocket), \"$1/\" + TRANSPORTS.longpoll))\n  }\n\n  endpointURL(){\n    return Ajax.appendParams(this.pollEndpoint, {token: this.token})\n  }\n\n  closeAndRetry(){\n    this.close()\n    this.readyState = SOCKET_STATES.connecting\n  }\n\n  ontimeout(){\n    this.onerror(\"timeout\")\n    this.closeAndRetry()\n  }\n\n  poll(){\n    if(!(this.readyState === SOCKET_STATES.open || this.readyState === SOCKET_STATES.connecting)){ return }\n\n    Ajax.request(\"GET\", this.endpointURL(), \"application/json\", null, this.timeout, this.ontimeout.bind(this), (resp) => {\n      if(resp){\n        var {status, token, messages} = resp\n        this.token = token\n      } else {\n        status = 0\n      }\n\n      switch(status){\n        case 200:\n          messages.forEach(msg => {\n            // Tasks are what things like event handlers, setTimeout callbacks,\n            // promise resolves and more are run within.\n            // In modern browsers, there are two different kinds of tasks,\n            // microtasks and macrotasks.\n            // Microtasks are mainly used for Promises, while macrotasks are\n            // used for everything else.\n            // Microtasks always have priority over macrotasks. If the JS engine\n            // is looking for a task to run, it will always try to empty the\n            // microtask queue before attempting to run anything from the\n            // macrotask queue.\n            //\n            // For the WebSocket transport, messages always arrive in their own\n            // event. This means that if any promises are resolved from within,\n            // their callbacks will always finish execution by the time the\n            // next message event handler is run.\n            //\n            // In order to emulate this behaviour, we need to make sure each\n            // onmessage handler is run within it's own macrotask.\n            setTimeout(() => {\n              this.onmessage({data: msg})\n            }, 0)\n          })\n          this.poll()\n          break\n        case 204:\n          this.poll()\n          break\n        case 410:\n          this.readyState = SOCKET_STATES.open\n          this.onopen()\n          this.poll()\n          break\n        case 403:\n          this.onerror()\n          this.close()\n          break\n        case 0:\n        case 500:\n          this.onerror()\n          this.closeAndRetry()\n          break\n        default: throw new Error(`unhandled poll status ${status}`)\n      }\n    })\n  }\n\n  send(body){\n    Ajax.request(\"POST\", this.endpointURL(), \"application/json\", body, this.timeout, this.onerror.bind(this, \"timeout\"), (resp) => {\n      if(!resp || resp.status !== 200){\n        this.onerror(resp && resp.status)\n        this.closeAndRetry()\n      }\n    })\n  }\n\n  close(_code, _reason){\n    this.readyState = SOCKET_STATES.closed\n    this.onclose()\n  }\n}\n", "/**\n * Initializes the Presence\n * @param {Channel} channel - The Channel\n * @param {Object} opts - The options,\n *        for example `{events: {state: \"state\", diff: \"diff\"}}`\n */\nexport default class Presence {\n\n  constructor(channel, opts = {}){\n    let events = opts.events || {state: \"presence_state\", diff: \"presence_diff\"}\n    this.state = {}\n    this.pendingDiffs = []\n    this.channel = channel\n    this.joinRef = null\n    this.caller = {\n      onJoin: function (){ },\n      onLeave: function (){ },\n      onSync: function (){ }\n    }\n\n    this.channel.on(events.state, newState => {\n      let {onJoin, onLeave, onSync} = this.caller\n\n      this.joinRef = this.channel.joinRef()\n      this.state = Presence.syncState(this.state, newState, onJoin, onLeave)\n\n      this.pendingDiffs.forEach(diff => {\n        this.state = Presence.syncDiff(this.state, diff, onJoin, onLeave)\n      })\n      this.pendingDiffs = []\n      onSync()\n    })\n\n    this.channel.on(events.diff, diff => {\n      let {onJoin, onLeave, onSync} = this.caller\n\n      if(this.inPendingSyncState()){\n        this.pendingDiffs.push(diff)\n      } else {\n        this.state = Presence.syncDiff(this.state, diff, onJoin, onLeave)\n        onSync()\n      }\n    })\n  }\n\n  onJoin(callback){ this.caller.onJoin = callback }\n\n  onLeave(callback){ this.caller.onLeave = callback }\n\n  onSync(callback){ this.caller.onSync = callback }\n\n  list(by){ return Presence.list(this.state, by) }\n\n  inPendingSyncState(){\n    return !this.joinRef || (this.joinRef !== this.channel.joinRef())\n  }\n\n  // lower-level public static API\n\n  /**\n   * Used to sync the list of presences on the server\n   * with the client's state. An optional `onJoin` and `onLeave` callback can\n   * be provided to react to changes in the client's local presences across\n   * disconnects and reconnects with the server.\n   *\n   * @returns {Presence}\n   */\n  static syncState(currentState, newState, onJoin, onLeave){\n    let state = this.clone(currentState)\n    let joins = {}\n    let leaves = {}\n\n    this.map(state, (key, presence) => {\n      if(!newState[key]){\n        leaves[key] = presence\n      }\n    })\n    this.map(newState, (key, newPresence) => {\n      let currentPresence = state[key]\n      if(currentPresence){\n        let newRefs = newPresence.metas.map(m => m.phx_ref)\n        let curRefs = currentPresence.metas.map(m => m.phx_ref)\n        let joinedMetas = newPresence.metas.filter(m => curRefs.indexOf(m.phx_ref) < 0)\n        let leftMetas = currentPresence.metas.filter(m => newRefs.indexOf(m.phx_ref) < 0)\n        if(joinedMetas.length > 0){\n          joins[key] = newPresence\n          joins[key].metas = joinedMetas\n        }\n        if(leftMetas.length > 0){\n          leaves[key] = this.clone(currentPresence)\n          leaves[key].metas = leftMetas\n        }\n      } else {\n        joins[key] = newPresence\n      }\n    })\n    return this.syncDiff(state, {joins: joins, leaves: leaves}, onJoin, onLeave)\n  }\n\n  /**\n   *\n   * Used to sync a diff of presence join and leave\n   * events from the server, as they happen. Like `syncState`, `syncDiff`\n   * accepts optional `onJoin` and `onLeave` callbacks to react to a user\n   * joining or leaving from a device.\n   *\n   * @returns {Presence}\n   */\n  static syncDiff(state, diff, onJoin, onLeave){\n    let {joins, leaves} = this.clone(diff)\n    if(!onJoin){ onJoin = function (){ } }\n    if(!onLeave){ onLeave = function (){ } }\n\n    this.map(joins, (key, newPresence) => {\n      let currentPresence = state[key]\n      state[key] = this.clone(newPresence)\n      if(currentPresence){\n        let joinedRefs = state[key].metas.map(m => m.phx_ref)\n        let curMetas = currentPresence.metas.filter(m => joinedRefs.indexOf(m.phx_ref) < 0)\n        state[key].metas.unshift(...curMetas)\n      }\n      onJoin(key, currentPresence, newPresence)\n    })\n    this.map(leaves, (key, leftPresence) => {\n      let currentPresence = state[key]\n      if(!currentPresence){ return }\n      let refsToRemove = leftPresence.metas.map(m => m.phx_ref)\n      currentPresence.metas = currentPresence.metas.filter(p => {\n        return refsToRemove.indexOf(p.phx_ref) < 0\n      })\n      onLeave(key, currentPresence, leftPresence)\n      if(currentPresence.metas.length === 0){\n        delete state[key]\n      }\n    })\n    return state\n  }\n\n  /**\n   * Returns the array of presences, with selected metadata.\n   *\n   * @param {Object} presences\n   * @param {Function} chooser\n   *\n   * @returns {Presence}\n   */\n  static list(presences, chooser){\n    if(!chooser){ chooser = function (key, pres){ return pres } }\n\n    return this.map(presences, (key, presence) => {\n      return chooser(key, presence)\n    })\n  }\n\n  // private\n\n  static map(obj, func){\n    return Object.getOwnPropertyNames(obj).map(key => func(key, obj[key]))\n  }\n\n  static clone(obj){ return JSON.parse(JSON.stringify(obj)) }\n}\n", "/* The default serializer for encoding and decoding messages */\nimport {\n  CHANNEL_EVENTS\n} from \"./constants\"\n\nexport default {\n  HEADER_LENGTH: 1,\n  META_LENGTH: 4,\n  KINDS: {push: 0, reply: 1, broadcast: 2},\n\n  encode(msg, callback){\n    if(msg.payload.constructor === ArrayBuffer){\n      return callback(this.binaryEncode(msg))\n    } else {\n      let payload = [msg.join_ref, msg.ref, msg.topic, msg.event, msg.payload]\n      return callback(JSON.stringify(payload))\n    }\n  },\n\n  decode(rawPayload, callback){\n    if(rawPayload.constructor === ArrayBuffer){\n      return callback(this.binaryDecode(rawPayload))\n    } else {\n      let [join_ref, ref, topic, event, payload] = JSON.parse(rawPayload)\n      return callback({join_ref, ref, topic, event, payload})\n    }\n  },\n\n  // private\n\n  binaryEncode(message){\n    let {join_ref, ref, event, topic, payload} = message\n    let metaLength = this.META_LENGTH + join_ref.length + ref.length + topic.length + event.length\n    let header = new ArrayBuffer(this.HEADER_LENGTH + metaLength)\n    let view = new DataView(header)\n    let offset = 0\n\n    view.setUint8(offset++, this.KINDS.push) // kind\n    view.setUint8(offset++, join_ref.length)\n    view.setUint8(offset++, ref.length)\n    view.setUint8(offset++, topic.length)\n    view.setUint8(offset++, event.length)\n    Array.from(join_ref, char => view.setUint8(offset++, char.charCodeAt(0)))\n    Array.from(ref, char => view.setUint8(offset++, char.charCodeAt(0)))\n    Array.from(topic, char => view.setUint8(offset++, char.charCodeAt(0)))\n    Array.from(event, char => view.setUint8(offset++, char.charCodeAt(0)))\n\n    var combined = new Uint8Array(header.byteLength + payload.byteLength)\n    combined.set(new Uint8Array(header), 0)\n    combined.set(new Uint8Array(payload), header.byteLength)\n\n    return combined.buffer\n  },\n\n  binaryDecode(buffer){\n    let view = new DataView(buffer)\n    let kind = view.getUint8(0)\n    let decoder = new TextDecoder()\n    switch(kind){\n      case this.KINDS.push: return this.decodePush(buffer, view, decoder)\n      case this.KINDS.reply: return this.decodeReply(buffer, view, decoder)\n      case this.KINDS.broadcast: return this.decodeBroadcast(buffer, view, decoder)\n    }\n  },\n\n  decodePush(buffer, view, decoder){\n    let joinRefSize = view.getUint8(1)\n    let topicSize = view.getUint8(2)\n    let eventSize = view.getUint8(3)\n    let offset = this.HEADER_LENGTH + this.META_LENGTH - 1 // pushes have no ref\n    let joinRef = decoder.decode(buffer.slice(offset, offset + joinRefSize))\n    offset = offset + joinRefSize\n    let topic = decoder.decode(buffer.slice(offset, offset + topicSize))\n    offset = offset + topicSize\n    let event = decoder.decode(buffer.slice(offset, offset + eventSize))\n    offset = offset + eventSize\n    let data = buffer.slice(offset, buffer.byteLength)\n    return {join_ref: joinRef, ref: null, topic: topic, event: event, payload: data}\n  },\n\n  decodeReply(buffer, view, decoder){\n    let joinRefSize = view.getUint8(1)\n    let refSize = view.getUint8(2)\n    let topicSize = view.getUint8(3)\n    let eventSize = view.getUint8(4)\n    let offset = this.HEADER_LENGTH + this.META_LENGTH\n    let joinRef = decoder.decode(buffer.slice(offset, offset + joinRefSize))\n    offset = offset + joinRefSize\n    let ref = decoder.decode(buffer.slice(offset, offset + refSize))\n    offset = offset + refSize\n    let topic = decoder.decode(buffer.slice(offset, offset + topicSize))\n    offset = offset + topicSize\n    let event = decoder.decode(buffer.slice(offset, offset + eventSize))\n    offset = offset + eventSize\n    let data = buffer.slice(offset, buffer.byteLength)\n    let payload = {status: event, response: data}\n    return {join_ref: joinRef, ref: ref, topic: topic, event: CHANNEL_EVENTS.reply, payload: payload}\n  },\n\n  decodeBroadcast(buffer, view, decoder){\n    let topicSize = view.getUint8(1)\n    let eventSize = view.getUint8(2)\n    let offset = this.HEADER_LENGTH + 2\n    let topic = decoder.decode(buffer.slice(offset, offset + topicSize))\n    offset = offset + topicSize\n    let event = decoder.decode(buffer.slice(offset, offset + eventSize))\n    offset = offset + eventSize\n    let data = buffer.slice(offset, buffer.byteLength)\n\n    return {join_ref: null, ref: null, topic: topic, event: event, payload: data}\n  }\n}\n", "import {\n  global,\n  phxWindow,\n  CHANNEL_EVENTS,\n  DEFAULT_TIMEOUT,\n  DEFAULT_VSN,\n  SOCKET_STATES,\n  TRANSPORTS,\n  WS_CLOSE_NORMAL\n} from \"./constants\"\n\nimport {\n  closure\n} from \"./utils\"\n\nimport Ajax from \"./ajax\"\nimport Channel from \"./channel\"\nimport LongPoll from \"./longpoll\"\nimport Serializer from \"./serializer\"\nimport Timer from \"./timer\"\n\n/** Initializes the Socket *\n *\n * For IE8 support use an ES5-shim (https://github.com/es-shims/es5-shim)\n *\n * @param {string} endPoint - The string WebSocket endpoint, ie, `\"ws://example.com/socket\"`,\n *                                               `\"wss://example.com\"`\n *                                               `\"/socket\"` (inherited host & protocol)\n * @param {Object} [opts] - Optional configuration\n * @param {Function} [opts.transport] - The Websocket Transport, for example WebSocket or Phoenix.LongPoll.\n *\n * Defaults to WebSocket with automatic LongPoll fallback.\n * @param {Function} [opts.encode] - The function to encode outgoing messages.\n *\n * Defaults to JSON encoder.\n *\n * @param {Function} [opts.decode] - The function to decode incoming messages.\n *\n * Defaults to JSON:\n *\n * ```javascript\n * (payload, callback) => callback(JSON.parse(payload))\n * ```\n *\n * @param {number} [opts.timeout] - The default timeout in milliseconds to trigger push timeouts.\n *\n * Defaults `DEFAULT_TIMEOUT`\n * @param {number} [opts.heartbeatIntervalMs] - The millisec interval to send a heartbeat message\n * @param {number} [opts.reconnectAfterMs] - The optional function that returns the millsec\n * socket reconnect interval.\n *\n * Defaults to stepped backoff of:\n *\n * ```javascript\n * function(tries){\n *   return [10, 50, 100, 150, 200, 250, 500, 1000, 2000][tries - 1] || 5000\n * }\n * ````\n *\n * @param {number} [opts.rejoinAfterMs] - The optional function that returns the millsec\n * rejoin interval for individual channels.\n *\n * ```javascript\n * function(tries){\n *   return [1000, 2000, 5000][tries - 1] || 10000\n * }\n * ````\n *\n * @param {Function} [opts.logger] - The optional function for specialized logging, ie:\n *\n * ```javascript\n * function(kind, msg, data) {\n *   console.log(`${kind}: ${msg}`, data)\n * }\n * ```\n *\n * @param {number} [opts.longpollerTimeout] - The maximum timeout of a long poll AJAX request.\n *\n * Defaults to 20s (double the server long poll timer).\n *\n * @param {{Object|function)} [opts.params] - The optional params to pass when connecting\n * @param {string} [opts.binaryType] - The binary type to use for binary WebSocket frames.\n *\n * Defaults to \"arraybuffer\"\n *\n * @param {vsn} [opts.vsn] - The serializer's protocol version to send on connect.\n *\n * Defaults to DEFAULT_VSN.\n*/\nexport default class Socket {\n  constructor(endPoint, opts = {}){\n    this.stateChangeCallbacks = {open: [], close: [], error: [], message: []}\n    this.channels = []\n    this.sendBuffer = []\n    this.ref = 0\n    this.timeout = opts.timeout || DEFAULT_TIMEOUT\n    this.transport = opts.transport || global.WebSocket || LongPoll\n    this.establishedConnections = 0\n    this.defaultEncoder = Serializer.encode.bind(Serializer)\n    this.defaultDecoder = Serializer.decode.bind(Serializer)\n    this.closeWasClean = false\n    this.binaryType = opts.binaryType || \"arraybuffer\"\n    this.connectClock = 1\n    if(this.transport !== LongPoll){\n      this.encode = opts.encode || this.defaultEncoder\n      this.decode = opts.decode || this.defaultDecoder\n    } else {\n      this.encode = this.defaultEncoder\n      this.decode = this.defaultDecoder\n    }\n    let awaitingConnectionOnPageShow = null\n    if(phxWindow && phxWindow.addEventListener){\n      phxWindow.addEventListener(\"pagehide\", _e => {\n        if(this.conn){\n          this.disconnect()\n          awaitingConnectionOnPageShow = this.connectClock\n        }\n      })\n      phxWindow.addEventListener(\"pageshow\", _e => {\n        if(awaitingConnectionOnPageShow === this.connectClock){\n          awaitingConnectionOnPageShow = null\n          this.connect()\n        }\n      })\n    }\n    this.heartbeatIntervalMs = opts.heartbeatIntervalMs || 30000\n    this.rejoinAfterMs = (tries) => {\n      if(opts.rejoinAfterMs){\n        return opts.rejoinAfterMs(tries)\n      } else {\n        return [1000, 2000, 5000][tries - 1] || 10000\n      }\n    }\n    this.reconnectAfterMs = (tries) => {\n      if(opts.reconnectAfterMs){\n        return opts.reconnectAfterMs(tries)\n      } else {\n        return [10, 50, 100, 150, 200, 250, 500, 1000, 2000][tries - 1] || 5000\n      }\n    }\n    this.logger = opts.logger || null\n    this.longpollerTimeout = opts.longpollerTimeout || 20000\n    this.params = closure(opts.params || {})\n    this.endPoint = `${endPoint}/${TRANSPORTS.websocket}`\n    this.vsn = opts.vsn || DEFAULT_VSN\n    this.heartbeatTimer = null\n    this.pendingHeartbeatRef = null\n    this.reconnectTimer = new Timer(() => {\n      this.teardown(() => this.connect())\n    }, this.reconnectAfterMs)\n  }\n\n  /**\n   * Disconnects and replaces the active transport\n   *\n   * @param {Function} newTransport - The new transport class to instantiate\n   *\n   */\n  replaceTransport(newTransport){\n    this.disconnect()\n    this.transport = newTransport\n  }\n\n  /**\n   * Returns the socket protocol\n   *\n   * @returns {string}\n   */\n  protocol(){ return location.protocol.match(/^https/) ? \"wss\" : \"ws\" }\n\n  /**\n   * The fully qualifed socket url\n   *\n   * @returns {string}\n   */\n  endPointURL(){\n    let uri = Ajax.appendParams(\n      Ajax.appendParams(this.endPoint, this.params()), {vsn: this.vsn})\n    if(uri.charAt(0) !== \"/\"){ return uri }\n    if(uri.charAt(1) === \"/\"){ return `${this.protocol()}:${uri}` }\n\n    return `${this.protocol()}://${location.host}${uri}`\n  }\n\n  /**\n   * Disconnects the socket\n   *\n   * See https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes for valid status codes.\n   *\n   * @param {Function} callback - Optional callback which is called after socket is disconnected.\n   * @param {integer} code - A status code for disconnection (Optional).\n   * @param {string} reason - A textual description of the reason to disconnect. (Optional)\n   */\n  disconnect(callback, code, reason){\n    this.connectClock++\n    this.closeWasClean = true\n    this.reconnectTimer.reset()\n    this.teardown(callback, code, reason)\n  }\n\n  /**\n   *\n   * @param {Object} params - The params to send when connecting, for example `{user_id: userToken}`\n   *\n   * Passing params to connect is deprecated; pass them in the Socket constructor instead:\n   * `new Socket(\"/socket\", {params: {user_id: userToken}})`.\n   */\n  connect(params){\n    this.connectClock++\n    if(params){\n      console && console.log(\"passing params to connect is deprecated. Instead pass :params to the Socket constructor\")\n      this.params = closure(params)\n    }\n    if(this.conn){ return }\n    this.closeWasClean = false\n    this.conn = new this.transport(this.endPointURL())\n    this.conn.binaryType = this.binaryType\n    this.conn.timeout = this.longpollerTimeout\n    this.conn.onopen = () => this.onConnOpen()\n    this.conn.onerror = error => this.onConnError(error)\n    this.conn.onmessage = event => this.onConnMessage(event)\n    this.conn.onclose = event => this.onConnClose(event)\n  }\n\n  /**\n   * Logs the message. Override `this.logger` for specialized logging. noops by default\n   * @param {string} kind\n   * @param {string} msg\n   * @param {Object} data\n   */\n  log(kind, msg, data){ this.logger(kind, msg, data) }\n\n  /**\n   * Returns true if a logger has been set on this socket.\n   */\n  hasLogger(){ return this.logger !== null }\n\n  /**\n   * Registers callbacks for connection open events\n   *\n   * @example socket.onOpen(function(){ console.info(\"the socket was opened\") })\n   *\n   * @param {Function} callback\n   */\n  onOpen(callback){\n    let ref = this.makeRef()\n    this.stateChangeCallbacks.open.push([ref, callback])\n    return ref\n  }\n\n  /**\n   * Registers callbacks for connection close events\n   * @param {Function} callback\n   */\n  onClose(callback){\n    let ref = this.makeRef()\n    this.stateChangeCallbacks.close.push([ref, callback])\n    return ref\n  }\n\n  /**\n   * Registers callbacks for connection error events\n   *\n   * @example socket.onError(function(error){ alert(\"An error occurred\") })\n   *\n   * @param {Function} callback\n   */\n  onError(callback){\n    let ref = this.makeRef()\n    this.stateChangeCallbacks.error.push([ref, callback])\n    return ref\n  }\n\n  /**\n   * Registers callbacks for connection message events\n   * @param {Function} callback\n   */\n  onMessage(callback){\n    let ref = this.makeRef()\n    this.stateChangeCallbacks.message.push([ref, callback])\n    return ref\n  }\n\n  /**\n   * @private\n   */\n  onConnOpen(){\n    if(this.hasLogger()) this.log(\"transport\", `connected to ${this.endPointURL()}`)\n    this.closeWasClean = false\n    this.establishedConnections++\n    this.flushSendBuffer()\n    this.reconnectTimer.reset()\n    this.resetHeartbeat()\n    this.stateChangeCallbacks.open.forEach(([, callback]) => callback())\n  }\n\n  /**\n   * @private\n   */\n\n  heartbeatTimeout(){\n    if(this.pendingHeartbeatRef){\n      this.pendingHeartbeatRef = null\n      if(this.hasLogger()){ this.log(\"transport\", \"heartbeat timeout. Attempting to re-establish connection\") }\n      this.abnormalClose(\"heartbeat timeout\")\n    }\n  }\n\n  resetHeartbeat(){\n    if(this.conn && this.conn.skipHeartbeat){ return }\n    this.pendingHeartbeatRef = null\n    clearTimeout(this.heartbeatTimer)\n    setTimeout(() => this.sendHeartbeat(), this.heartbeatIntervalMs)\n  }\n\n  teardown(callback, code, reason){\n    if(!this.conn){\n      return callback && callback()\n    }\n\n    this.waitForBufferDone(() => {\n      if(this.conn){\n        if(code){ this.conn.close(code, reason || \"\") } else { this.conn.close() }\n      }\n\n      this.waitForSocketClosed(() => {\n        if(this.conn){\n          this.conn.onclose = function (){ } // noop\n          this.conn = null\n        }\n\n        callback && callback()\n      })\n    })\n  }\n\n  waitForBufferDone(callback, tries = 1){\n    if(tries === 5 || !this.conn || !this.conn.bufferedAmount){\n      callback()\n      return\n    }\n\n    setTimeout(() => {\n      this.waitForBufferDone(callback, tries + 1)\n    }, 150 * tries)\n  }\n\n  waitForSocketClosed(callback, tries = 1){\n    if(tries === 5 || !this.conn || this.conn.readyState === SOCKET_STATES.closed){\n      callback()\n      return\n    }\n\n    setTimeout(() => {\n      this.waitForSocketClosed(callback, tries + 1)\n    }, 150 * tries)\n  }\n\n  onConnClose(event){\n    let closeCode = event && event.code\n    if(this.hasLogger()) this.log(\"transport\", \"close\", event)\n    this.triggerChanError()\n    clearTimeout(this.heartbeatTimer)\n    if(!this.closeWasClean && closeCode !== 1000){\n      this.reconnectTimer.scheduleTimeout()\n    }\n    this.stateChangeCallbacks.close.forEach(([, callback]) => callback(event))\n  }\n\n  /**\n   * @private\n   */\n  onConnError(error){\n    if(this.hasLogger()) this.log(\"transport\", error)\n    let transportBefore = this.transport\n    let establishedBefore = this.establishedConnections\n    this.stateChangeCallbacks.error.forEach(([, callback]) => {\n      callback(error, transportBefore, establishedBefore)\n    })\n    if(transportBefore === this.transport || establishedBefore > 0){\n      this.triggerChanError()\n    }\n  }\n\n  /**\n   * @private\n   */\n  triggerChanError(){\n    this.channels.forEach(channel => {\n      if(!(channel.isErrored() || channel.isLeaving() || channel.isClosed())){\n        channel.trigger(CHANNEL_EVENTS.error)\n      }\n    })\n  }\n\n  /**\n   * @returns {string}\n   */\n  connectionState(){\n    switch(this.conn && this.conn.readyState){\n      case SOCKET_STATES.connecting: return \"connecting\"\n      case SOCKET_STATES.open: return \"open\"\n      case SOCKET_STATES.closing: return \"closing\"\n      default: return \"closed\"\n    }\n  }\n\n  /**\n   * @returns {boolean}\n   */\n  isConnected(){ return this.connectionState() === \"open\" }\n\n  /**\n   * @private\n   *\n   * @param {Channel}\n   */\n  remove(channel){\n    this.off(channel.stateChangeRefs)\n    this.channels = this.channels.filter(c => c.joinRef() !== channel.joinRef())\n  }\n\n  /**\n   * Removes `onOpen`, `onClose`, `onError,` and `onMessage` registrations.\n   *\n   * @param {refs} - list of refs returned by calls to\n   *                 `onOpen`, `onClose`, `onError,` and `onMessage`\n   */\n  off(refs){\n    for(let key in this.stateChangeCallbacks){\n      this.stateChangeCallbacks[key] = this.stateChangeCallbacks[key].filter(([ref]) => {\n        return refs.indexOf(ref) === -1\n      })\n    }\n  }\n\n  /**\n   * Initiates a new channel for the given topic\n   *\n   * @param {string} topic\n   * @param {Object} chanParams - Parameters for the channel\n   * @returns {Channel}\n   */\n  channel(topic, chanParams = {}){\n    let chan = new Channel(topic, chanParams, this)\n    this.channels.push(chan)\n    return chan\n  }\n\n  /**\n   * @param {Object} data\n   */\n  push(data){\n    if(this.hasLogger()){\n      let {topic, event, payload, ref, join_ref} = data\n      this.log(\"push\", `${topic} ${event} (${join_ref}, ${ref})`, payload)\n    }\n\n    if(this.isConnected()){\n      this.encode(data, result => this.conn.send(result))\n    } else {\n      this.sendBuffer.push(() => this.encode(data, result => this.conn.send(result)))\n    }\n  }\n\n  /**\n   * Return the next message ref, accounting for overflows\n   * @returns {string}\n   */\n  makeRef(){\n    let newRef = this.ref + 1\n    if(newRef === this.ref){ this.ref = 0 } else { this.ref = newRef }\n\n    return this.ref.toString()\n  }\n\n  sendHeartbeat(){\n    if(this.pendingHeartbeatRef && !this.isConnected()){ return }\n    this.pendingHeartbeatRef = this.makeRef()\n    this.push({topic: \"phoenix\", event: \"heartbeat\", payload: {}, ref: this.pendingHeartbeatRef})\n    this.heartbeatTimer = setTimeout(() => this.heartbeatTimeout(), this.heartbeatIntervalMs)\n  }\n\n  abnormalClose(reason){\n    this.closeWasClean = false\n    if(this.isConnected()){ this.conn.close(WS_CLOSE_NORMAL, reason) }\n  }\n\n  flushSendBuffer(){\n    if(this.isConnected() && this.sendBuffer.length > 0){\n      this.sendBuffer.forEach(callback => callback())\n      this.sendBuffer = []\n    }\n  }\n\n  onConnMessage(rawMessage){\n    this.decode(rawMessage.data, msg => {\n      let {topic, event, payload, ref, join_ref} = msg\n      if(ref && ref === this.pendingHeartbeatRef){\n        clearTimeout(this.heartbeatTimer)\n        this.pendingHeartbeatRef = null\n        setTimeout(() => this.sendHeartbeat(), this.heartbeatIntervalMs)\n      }\n\n      if(this.hasLogger()) this.log(\"receive\", `${payload.status || \"\"} ${topic} ${event} ${ref && \"(\" + ref + \")\" || \"\"}`, payload)\n\n      for(let i = 0; i < this.channels.length; i++){\n        const channel = this.channels[i]\n        if(!channel.isMember(topic, event, payload, join_ref)){ continue }\n        channel.trigger(event, payload, ref, join_ref)\n      }\n\n      for(let i = 0; i < this.stateChangeCallbacks.message.length; i++){\n        let [, callback] = this.stateChangeCallbacks.message[i]\n        callback(msg)\n      }\n    })\n  }\n\n  leaveOpenTopic(topic){\n    let dupChannel = this.channels.find(c => c.topic === topic && (c.isJoined() || c.isJoining()))\n    if(dupChannel){\n      if(this.hasLogger()) this.log(\"transport\", `leaving duplicate topic \"${topic}\"`)\n      dupChannel.leave()\n    }\n  }\n}\n", "\"use strict\";\n\n(function() {\n  var PolyfillEvent = eventConstructor();\n\n  function eventConstructor() {\n    if (typeof window.CustomEvent === \"function\") return window.CustomEvent;\n    // IE<=9 Support\n    function CustomEvent(event, params) {\n      params = params || {bubbles: false, cancelable: false, detail: undefined};\n      var evt = document.createEvent('CustomEvent');\n      evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);\n      return evt;\n    }\n    CustomEvent.prototype = window.Event.prototype;\n    return CustomEvent;\n  }\n\n  function buildHiddenInput(name, value) {\n    var input = document.createElement(\"input\");\n    input.type = \"hidden\";\n    input.name = name;\n    input.value = value;\n    return input;\n  }\n\n  function handleClick(element, targetModifierKey) {\n    var to = element.getAttribute(\"data-to\"),\n        method = buildHiddenInput(\"_method\", element.getAttribute(\"data-method\")),\n        csrf = buildHiddenInput(\"_csrf_token\", element.getAttribute(\"data-csrf\")),\n        form = document.createElement(\"form\"),\n        target = element.getAttribute(\"target\");\n\n    form.method = (element.getAttribute(\"data-method\") === \"get\") ? \"get\" : \"post\";\n    form.action = to;\n    form.style.display = \"hidden\";\n\n    if (target) form.target = target;\n    else if (targetModifierKey) form.target = \"_blank\";\n\n    form.appendChild(csrf);\n    form.appendChild(method);\n    document.body.appendChild(form);\n    form.submit();\n  }\n\n  window.addEventListener(\"click\", function(e) {\n    var element = e.target;\n    if (e.defaultPrevented) return;\n\n    while (element && element.getAttribute) {\n      var phoenixLinkEvent = new PolyfillEvent('phoenix.link.click', {\n        \"bubbles\": true, \"cancelable\": true\n      });\n\n      if (!element.dispatchEvent(phoenixLinkEvent)) {\n        e.preventDefault();\n        e.stopImmediatePropagation();\n        return false;\n      }\n\n      if (element.getAttribute(\"data-method\")) {\n        handleClick(element, e.metaKey || e.shiftKey);\n        e.preventDefault();\n        return false;\n      } else {\n        element = element.parentNode;\n      }\n    }\n  }, false);\n\n  window.addEventListener('phoenix.link.click', function (e) {\n    var message = e.target.getAttribute(\"data-confirm\");\n    if(message && !window.confirm(message)) {\n      e.preventDefault();\n    }\n  }, false);\n})();\n", "\nexport const CONSECUTIVE_RELOADS = \"consecutive-reloads\"\nexport const MAX_RELOADS = 10\nexport const RELOAD_JITTER = [1000, 3000]\nexport const FAILSAFE_JITTER = 30000\nexport const PHX_EVENT_CLASSES = [\n  \"phx-click-loading\", \"phx-change-loading\", \"phx-submit-loading\",\n  \"phx-keydown-loading\", \"phx-keyup-loading\", \"phx-blur-loading\", \"phx-focus-loading\"\n]\nexport const PHX_COMPONENT = \"data-phx-component\"\nexport const PHX_LIVE_LINK = \"data-phx-link\"\nexport const PHX_TRACK_STATIC = \"track-static\"\nexport const PHX_LINK_STATE = \"data-phx-link-state\"\nexport const PHX_REF = \"data-phx-ref\"\nexport const PHX_TRACK_UPLOADS = \"track-uploads\"\nexport const PHX_UPLOAD_REF = \"data-phx-upload-ref\"\nexport const PHX_PREFLIGHTED_REFS = \"data-phx-preflighted-refs\"\nexport const PHX_DONE_REFS = \"data-phx-done-refs\"\nexport const PHX_DROP_TARGET = \"drop-target\"\nexport const PHX_ACTIVE_ENTRY_REFS = \"data-phx-active-refs\"\nexport const PHX_LIVE_FILE_UPDATED = \"phx:live-file:updated\"\nexport const PHX_SKIP = \"data-phx-skip\"\nexport const PHX_PRUNE = \"data-phx-prune\"\nexport const PHX_PAGE_LOADING = \"page-loading\"\nexport const PHX_CONNECTED_CLASS = \"phx-connected\"\nexport const PHX_DISCONNECTED_CLASS = \"phx-loading\"\nexport const PHX_NO_FEEDBACK_CLASS = \"phx-no-feedback\"\nexport const PHX_ERROR_CLASS = \"phx-error\"\nexport const PHX_PARENT_ID = \"data-phx-parent-id\"\nexport const PHX_MAIN = \"data-phx-main\"\nexport const PHX_ROOT_ID = \"data-phx-root-id\"\nexport const PHX_TRIGGER_ACTION = \"trigger-action\"\nexport const PHX_FEEDBACK_FOR = \"feedback-for\"\nexport const PHX_HAS_FOCUSED = \"phx-has-focused\"\nexport const FOCUSABLE_INPUTS = [\"text\", \"textarea\", \"number\", \"email\", \"password\", \"search\", \"tel\", \"url\", \"date\", \"time\"]\nexport const CHECKABLE_INPUTS = [\"checkbox\", \"radio\"]\nexport const PHX_HAS_SUBMITTED = \"phx-has-submitted\"\nexport const PHX_SESSION = \"data-phx-session\"\nexport const PHX_VIEW_SELECTOR = `[${PHX_SESSION}]`\nexport const PHX_STATIC = \"data-phx-static\"\nexport const PHX_READONLY = \"data-phx-readonly\"\nexport const PHX_DISABLED = \"data-phx-disabled\"\nexport const PHX_DISABLE_WITH = \"disable-with\"\nexport const PHX_DISABLE_WITH_RESTORE = \"data-phx-disable-with-restore\"\nexport const PHX_HOOK = \"hook\"\nexport const PHX_DEBOUNCE = \"debounce\"\nexport const PHX_THROTTLE = \"throttle\"\nexport const PHX_UPDATE = \"update\"\nexport const PHX_KEY = \"key\"\nexport const PHX_PRIVATE = \"phxPrivate\"\nexport const PHX_AUTO_RECOVER = \"auto-recover\"\nexport const PHX_LV_DEBUG = \"phx:live-socket:debug\"\nexport const PHX_LV_PROFILE = \"phx:live-socket:profiling\"\nexport const PHX_LV_LATENCY_SIM = \"phx:live-socket:latency-sim\"\nexport const PHX_PROGRESS = \"progress\"\nexport const LOADER_TIMEOUT = 1\nexport const BEFORE_UNLOAD_LOADER_TIMEOUT = 200\nexport const BINDING_PREFIX = \"phx-\"\nexport const PUSH_TIMEOUT = 30000\nexport const LINK_HEADER = \"x-requested-with\"\nexport const RESPONSE_URL_HEADER = \"x-response-url\"\nexport const DEBOUNCE_TRIGGER = \"debounce-trigger\"\nexport const THROTTLED = \"throttled\"\nexport const DEBOUNCE_PREV_KEY = \"debounce-prev-key\"\nexport const DEFAULTS = {\n  debounce: 300,\n  throttle: 300\n}\n\n// Rendered\nexport const DYNAMICS = \"d\"\nexport const STATIC = \"s\"\nexport const COMPONENTS = \"c\"\nexport const EVENTS = \"e\"\nexport const REPLY = \"r\"\nexport const TITLE = \"t\"\nexport const TEMPLATES = \"p\"\n", "import {\n  logError\n} from \"./utils\"\n\nexport default class EntryUploader {\n  constructor(entry, chunkSize, liveSocket){\n    this.liveSocket = liveSocket\n    this.entry = entry\n    this.offset = 0\n    this.chunkSize = chunkSize\n    this.chunkTimer = null\n    this.uploadChannel = liveSocket.channel(`lvu:${entry.ref}`, {token: entry.metadata()})\n  }\n\n  error(reason){\n    clearTimeout(this.chunkTimer)\n    this.uploadChannel.leave()\n    this.entry.error(reason)\n  }\n\n  upload(){\n    this.uploadChannel.onError(reason => this.error(reason))\n    this.uploadChannel.join()\n      .receive(\"ok\", _data => this.readNextChunk())\n      .receive(\"error\", reason => this.error(reason))\n  }\n\n  isDone(){ return this.offset >= this.entry.file.size }\n\n  readNextChunk(){\n    let reader = new window.FileReader()\n    let blob = this.entry.file.slice(this.offset, this.chunkSize + this.offset)\n    reader.onload = (e) => {\n      if(e.target.error === null){\n        this.offset += e.target.result.byteLength\n        this.pushChunk(e.target.result)\n      } else {\n        return logError(\"Read error: \" + e.target.error)\n      }\n    }\n    reader.readAsArrayBuffer(blob)\n  }\n\n  pushChunk(chunk){\n    if(!this.uploadChannel.isJoined()){ return }\n    this.uploadChannel.push(\"chunk\", chunk)\n      .receive(\"ok\", () => {\n        this.entry.progress((this.offset / this.entry.file.size) * 100)\n        if(!this.isDone()){\n          this.chunkTimer = setTimeout(() => this.readNextChunk(), this.liveSocket.getLatencySim() || 0)\n        }\n      })\n  }\n}\n", "import {\n  PHX_VIEW_SELECTOR\n} from \"./constants\"\n\nimport EntryUploader from \"./entry_uploader\"\n\nexport let logError = (msg, obj) => console.error && console.error(msg, obj)\n\nexport let isCid = (cid) => {\n  let type = typeof(cid)\n  return type === \"number\" || (type === \"string\" && /^(0|[1-9]\\d*)$/.test(cid))\n}\n\nexport function detectDuplicateIds(){\n  let ids = new Set()\n  let elems = document.querySelectorAll(\"*[id]\")\n  for(let i = 0, len = elems.length; i < len; i++){\n    if(ids.has(elems[i].id)){\n      console.error(`Multiple IDs detected: ${elems[i].id}. Ensure unique element ids.`)\n    } else {\n      ids.add(elems[i].id)\n    }\n  }\n}\n\nexport let debug = (view, kind, msg, obj) => {\n  if(view.liveSocket.isDebugEnabled()){\n    console.log(`${view.id} ${kind}: ${msg} - `, obj)\n  }\n}\n\n// wraps value in closure or returns closure\nexport let closure = (val) => typeof val === \"function\" ? val : function (){ return val }\n\nexport let clone = (obj) => { return JSON.parse(JSON.stringify(obj)) }\n\nexport let closestPhxBinding = (el, binding, borderEl) => {\n  do {\n    if(el.matches(`[${binding}]`)){ return el }\n    el = el.parentElement || el.parentNode\n  } while(el !== null && el.nodeType === 1 && !((borderEl && borderEl.isSameNode(el)) || el.matches(PHX_VIEW_SELECTOR)))\n  return null\n}\n\nexport let isObject = (obj) => {\n  return obj !== null && typeof obj === \"object\" && !(obj instanceof Array)\n}\n\nexport let isEqualObj = (obj1, obj2) => JSON.stringify(obj1) === JSON.stringify(obj2)\n\nexport let isEmpty = (obj) => {\n  for(let x in obj){ return false }\n  return true\n}\n\nexport let maybe = (el, callback) => el && callback(el)\n\nexport let channelUploader = function (entries, onError, resp, liveSocket){\n  entries.forEach(entry => {\n    let entryUploader = new EntryUploader(entry, resp.config.chunk_size, liveSocket)\n    entryUploader.upload()\n  })\n}\n", "let Browser = {\n  canPushState(){ return (typeof (history.pushState) !== \"undefined\") },\n\n  dropLocal(localStorage, namespace, subkey){\n    return localStorage.removeItem(this.localKey(namespace, subkey))\n  },\n\n  updateLocal(localStorage, namespace, subkey, initial, func){\n    let current = this.getLocal(localStorage, namespace, subkey)\n    let key = this.localKey(namespace, subkey)\n    let newVal = current === null ? initial : func(current)\n    localStorage.setItem(key, JSON.stringify(newVal))\n    return newVal\n  },\n\n  getLocal(localStorage, namespace, subkey){\n    return JSON.parse(localStorage.getItem(this.localKey(namespace, subkey)))\n  },\n\n  updateCurrentState(callback){\n    if(!this.canPushState()){ return }\n    history.replaceState(callback(history.state || {}), \"\", window.location.href)\n  },\n\n  pushState(kind, meta, to){\n    if(this.canPushState()){\n      if(to !== window.location.href){\n        if(meta.type == \"redirect\" && meta.scroll){\n          // If we're redirecting store the current scrollY for the current history state.\n          let currentState = history.state || {}\n          currentState.scroll = meta.scroll\n          history.replaceState(currentState, \"\", window.location.href)\n        }\n\n        delete meta.scroll // Only store the scroll in the redirect case.\n        history[kind + \"State\"](meta, \"\", to || null) // IE will coerce undefined to string\n        let hashEl = this.getHashTargetEl(window.location.hash)\n\n        if(hashEl){\n          hashEl.scrollIntoView()\n        } else if(meta.type === \"redirect\"){\n          window.scroll(0, 0)\n        }\n      }\n    } else {\n      this.redirect(to)\n    }\n  },\n\n  setCookie(name, value){\n    document.cookie = `${name}=${value}`\n  },\n\n  getCookie(name){\n    return document.cookie.replace(new RegExp(`(?:(?:^|.*;\\s*)${name}\\s*\\=\\s*([^;]*).*$)|^.*$`), \"$1\")\n  },\n\n  redirect(toURL, flash){\n    if(flash){ Browser.setCookie(\"__phoenix_flash__\", flash + \"; max-age=60000; path=/\") }\n    window.location = toURL\n  },\n\n  localKey(namespace, subkey){ return `${namespace}-${subkey}` },\n\n  getHashTargetEl(maybeHash){\n    let hash = maybeHash.toString().substring(1)\n    if(hash === \"\"){ return }\n    return document.getElementById(hash) || document.querySelector(`a[name=\"${hash}\"]`)\n  }\n}\n\nexport default Browser\n", "import {\n  CHECKABLE_INPUTS,\n  DEBOUNCE_PREV_KEY,\n  DEBOUNCE_TRIGGER,\n  FOCUSABLE_INPUTS,\n  PHX_COMPONENT,\n  PHX_EVENT_CLASSES,\n  PHX_HAS_FOCUSED,\n  PHX_HAS_SUBMITTED,\n  PHX_MAIN,\n  PHX_NO_FEEDBACK_CLASS,\n  PHX_PARENT_ID,\n  PHX_PRIVATE,\n  PHX_REF,\n  PHX_ROOT_ID,\n  PHX_SESSION,\n  PHX_STATIC,\n  PHX_UPLOAD_REF,\n  PHX_VIEW_SELECTOR,\n  THROTTLED\n} from \"./constants\"\n\nimport {\n  logError\n} from \"./utils\"\n\nlet DOM = {\n  byId(id){ return document.getElementById(id) || logError(`no id found for ${id}`) },\n\n  removeClass(el, className){\n    el.classList.remove(className)\n    if(el.classList.length === 0){ el.removeAttribute(\"class\") }\n  },\n\n  all(node, query, callback){\n    if(!node){ return [] }\n    let array = Array.from(node.querySelectorAll(query))\n    return callback ? array.forEach(callback) : array\n  },\n\n  childNodeLength(html){\n    let template = document.createElement(\"template\")\n    template.innerHTML = html\n    return template.content.childElementCount\n  },\n\n  isUploadInput(el){ return el.type === \"file\" && el.getAttribute(PHX_UPLOAD_REF) !== null },\n\n  findUploadInputs(node){ return this.all(node, `input[type=\"file\"][${PHX_UPLOAD_REF}]`) },\n\n  findComponentNodeList(node, cid){\n    return this.filterWithinSameLiveView(this.all(node, `[${PHX_COMPONENT}=\"${cid}\"]`), node)\n  },\n\n  isPhxDestroyed(node){\n    return node.id && DOM.private(node, \"destroyed\") ? true : false\n  },\n\n  markPhxChildDestroyed(el){\n    if(this.isPhxChild(el)){ el.setAttribute(PHX_SESSION, \"\") }\n    this.putPrivate(el, \"destroyed\", true)\n  },\n\n  findPhxChildrenInFragment(html, parentId){\n    let template = document.createElement(\"template\")\n    template.innerHTML = html\n    return this.findPhxChildren(template.content, parentId)\n  },\n\n  isIgnored(el, phxUpdate){\n    return (el.getAttribute(phxUpdate) || el.getAttribute(\"data-phx-update\")) === \"ignore\"\n  },\n\n  isPhxUpdate(el, phxUpdate, updateTypes){\n    return el.getAttribute && updateTypes.indexOf(el.getAttribute(phxUpdate)) >= 0\n  },\n\n  findPhxChildren(el, parentId){\n    return this.all(el, `${PHX_VIEW_SELECTOR}[${PHX_PARENT_ID}=\"${parentId}\"]`)\n  },\n\n  findParentCIDs(node, cids){\n    let initial = new Set(cids)\n    return cids.reduce((acc, cid) => {\n      let selector = `[${PHX_COMPONENT}=\"${cid}\"] [${PHX_COMPONENT}]`\n\n      this.filterWithinSameLiveView(this.all(node, selector), node)\n        .map(el => parseInt(el.getAttribute(PHX_COMPONENT)))\n        .forEach(childCID => acc.delete(childCID))\n\n      return acc\n    }, initial)\n  },\n\n  filterWithinSameLiveView(nodes, parent){\n    if(parent.querySelector(PHX_VIEW_SELECTOR)){\n      return nodes.filter(el => this.withinSameLiveView(el, parent))\n    } else {\n      return nodes\n    }\n  },\n\n  withinSameLiveView(node, parent){\n    while(node = node.parentNode){\n      if(node.isSameNode(parent)){ return true }\n      if(node.getAttribute(PHX_SESSION) !== null){ return false }\n    }\n  },\n\n  private(el, key){ return el[PHX_PRIVATE] && el[PHX_PRIVATE][key] },\n\n  deletePrivate(el, key){ el[PHX_PRIVATE] && delete (el[PHX_PRIVATE][key]) },\n\n  putPrivate(el, key, value){\n    if(!el[PHX_PRIVATE]){ el[PHX_PRIVATE] = {} }\n    el[PHX_PRIVATE][key] = value\n  },\n\n  updatePrivate(el, key, defaultVal, updateFunc){\n    let existing = this.private(el, key)\n    if(existing === undefined){\n      this.putPrivate(el, key, updateFunc(defaultVal))\n    } else {\n      this.putPrivate(el, key, updateFunc(existing))\n    }\n  },\n\n  copyPrivates(target, source){\n    if(source[PHX_PRIVATE]){\n      target[PHX_PRIVATE] = source[PHX_PRIVATE]\n    }\n  },\n\n  putTitle(str){\n    let titleEl = document.querySelector(\"title\")\n    let {prefix, suffix} = titleEl.dataset\n    document.title = `${prefix || \"\"}${str}${suffix || \"\"}`\n  },\n\n  debounce(el, event, phxDebounce, defaultDebounce, phxThrottle, defaultThrottle, callback){\n    let debounce = el.getAttribute(phxDebounce)\n    let throttle = el.getAttribute(phxThrottle)\n    if(debounce === \"\"){ debounce = defaultDebounce }\n    if(throttle === \"\"){ throttle = defaultThrottle }\n    let value = debounce || throttle\n    switch(value){\n      case null: return callback()\n\n      case \"blur\":\n        if(this.once(el, \"debounce-blur\")){\n          el.addEventListener(\"blur\", () => callback())\n        }\n        return\n\n      default:\n        let timeout = parseInt(value)\n        let trigger = () => throttle ? this.deletePrivate(el, THROTTLED) : callback()\n        let currentCycle = this.incCycle(el, DEBOUNCE_TRIGGER, trigger)\n        if(isNaN(timeout)){ return logError(`invalid throttle/debounce value: ${value}`) }\n        if(throttle){\n          let newKeyDown = false\n          if(event.type === \"keydown\"){\n            let prevKey = this.private(el, DEBOUNCE_PREV_KEY)\n            this.putPrivate(el, DEBOUNCE_PREV_KEY, event.key)\n            newKeyDown = prevKey !== event.key\n          }\n\n          if(!newKeyDown && this.private(el, THROTTLED)){\n            return false\n          } else {\n            callback()\n            this.putPrivate(el, THROTTLED, true)\n            setTimeout(() => this.triggerCycle(el, DEBOUNCE_TRIGGER), timeout)\n          }\n        } else {\n          setTimeout(() => this.triggerCycle(el, DEBOUNCE_TRIGGER, currentCycle), timeout)\n        }\n\n\n        let form = el.form\n        if(form && this.once(form, \"bind-debounce\")){\n          form.addEventListener(\"submit\", () => {\n            Array.from((new FormData(form)).entries(), ([name]) => {\n              let input = form.querySelector(`[name=\"${name}\"]`)\n              this.incCycle(input, DEBOUNCE_TRIGGER)\n              this.deletePrivate(input, THROTTLED)\n            })\n          })\n        }\n        if(this.once(el, \"bind-debounce\")){\n          el.addEventListener(\"blur\", () => this.triggerCycle(el, DEBOUNCE_TRIGGER))\n        }\n    }\n  },\n\n  triggerCycle(el, key, currentCycle){\n    let [cycle, trigger] = this.private(el, key)\n    if(!currentCycle){ currentCycle = cycle }\n    if(currentCycle === cycle){\n      this.incCycle(el, key)\n      trigger()\n    }\n  },\n\n  once(el, key){\n    if(this.private(el, key) === true){ return false }\n    this.putPrivate(el, key, true)\n    return true\n  },\n\n  incCycle(el, key, trigger = function (){ }){\n    let [currentCycle] = this.private(el, key) || [0, trigger]\n    currentCycle++\n    this.putPrivate(el, key, [currentCycle, trigger])\n    return currentCycle\n  },\n\n  discardError(container, el, phxFeedbackFor){\n    let field = el.getAttribute && el.getAttribute(phxFeedbackFor)\n    // TODO: Remove id lookup after we update Phoenix to use input_name instead of input_id\n    let input = field && container.querySelector(`[id=\"${field}\"], [name=\"${field}\"]`)\n    if(!input){ return }\n\n    if(!(this.private(input, PHX_HAS_FOCUSED) || this.private(input.form, PHX_HAS_SUBMITTED))){\n      el.classList.add(PHX_NO_FEEDBACK_CLASS)\n    }\n  },\n\n  showError(inputEl, phxFeedbackFor){\n    if(inputEl.id || inputEl.name){\n      this.all(inputEl.form, `[${phxFeedbackFor}=\"${inputEl.id}\"], [${phxFeedbackFor}=\"${inputEl.name}\"]`, (el) => {\n        this.removeClass(el, PHX_NO_FEEDBACK_CLASS)\n      })\n    }\n  },\n\n  isPhxChild(node){\n    return node.getAttribute && node.getAttribute(PHX_PARENT_ID)\n  },\n\n  firstPhxChild(el){\n    return this.isPhxChild(el) ? el : this.all(el, `[${PHX_PARENT_ID}]`)[0]\n  },\n\n  dispatchEvent(target, eventString, detail = {}){\n    let event = new CustomEvent(eventString, {bubbles: true, cancelable: true, detail: detail})\n    target.dispatchEvent(event)\n  },\n\n  cloneNode(node, html){\n    if(typeof (html) === \"undefined\"){\n      return node.cloneNode(true)\n    } else {\n      let cloned = node.cloneNode(false)\n      cloned.innerHTML = html\n      return cloned\n    }\n  },\n\n  mergeAttrs(target, source, opts = {}){\n    let exclude = opts.exclude || []\n    let isIgnored = opts.isIgnored\n    let sourceAttrs = source.attributes\n    for(let i = sourceAttrs.length - 1; i >= 0; i--){\n      let name = sourceAttrs[i].name\n      if(exclude.indexOf(name) < 0){ target.setAttribute(name, source.getAttribute(name)) }\n    }\n\n    let targetAttrs = target.attributes\n    for(let i = targetAttrs.length - 1; i >= 0; i--){\n      let name = targetAttrs[i].name\n      if(isIgnored){\n        if(name.startsWith(\"data-\") && !source.hasAttribute(name)){ target.removeAttribute(name) }\n      } else {\n        if(!source.hasAttribute(name)){ target.removeAttribute(name) }\n      }\n    }\n  },\n\n  mergeFocusedInput(target, source){\n    // skip selects because FF will reset highlighted index for any setAttribute\n    if(!(target instanceof HTMLSelectElement)){ DOM.mergeAttrs(target, source, {except: [\"value\"]}) }\n    if(source.readOnly){\n      target.setAttribute(\"readonly\", true)\n    } else {\n      target.removeAttribute(\"readonly\")\n    }\n  },\n\n  hasSelectionRange(el){\n    return el.setSelectionRange && (el.type === \"text\" || el.type === \"textarea\")\n  },\n\n  restoreFocus(focused, selectionStart, selectionEnd){\n    if(!DOM.isTextualInput(focused)){ return }\n    let wasFocused = focused.matches(\":focus\")\n    if(focused.readOnly){ focused.blur() }\n    if(!wasFocused){ focused.focus() }\n    if(this.hasSelectionRange(focused)){\n      focused.setSelectionRange(selectionStart, selectionEnd)\n    }\n  },\n\n  isFormInput(el){ return /^(?:input|select|textarea)$/i.test(el.tagName) && el.type !== \"button\" },\n\n  syncAttrsToProps(el){\n    if(el instanceof HTMLInputElement && CHECKABLE_INPUTS.indexOf(el.type.toLocaleLowerCase()) >= 0){\n      el.checked = el.getAttribute(\"checked\") !== null\n    }\n  },\n\n  isTextualInput(el){ return FOCUSABLE_INPUTS.indexOf(el.type) >= 0 },\n\n  isNowTriggerFormExternal(el, phxTriggerExternal){\n    return el.getAttribute && el.getAttribute(phxTriggerExternal) !== null\n  },\n\n  syncPendingRef(fromEl, toEl, disableWith){\n    let ref = fromEl.getAttribute(PHX_REF)\n    if(ref === null){ return true }\n\n    if(DOM.isFormInput(fromEl) || fromEl.getAttribute(disableWith) !== null){\n      if(DOM.isUploadInput(fromEl)){ DOM.mergeAttrs(fromEl, toEl, {isIgnored: true}) }\n      DOM.putPrivate(fromEl, PHX_REF, toEl)\n      return false\n    } else {\n      PHX_EVENT_CLASSES.forEach(className => {\n        fromEl.classList.contains(className) && toEl.classList.add(className)\n      })\n      toEl.setAttribute(PHX_REF, ref)\n      return true\n    }\n  },\n\n  cleanChildNodes(container, phxUpdate){\n    if(DOM.isPhxUpdate(container, phxUpdate, [\"append\", \"prepend\"])){\n      let toRemove = []\n      container.childNodes.forEach(childNode => {\n        if(!childNode.id){\n          // Skip warning if it's an empty text node (e.g. a new-line)\n          let isEmptyTextNode = childNode.nodeType === Node.TEXT_NODE && childNode.nodeValue.trim() === \"\"\n          if(!isEmptyTextNode){\n            logError(\"only HTML element tags with an id are allowed inside containers with phx-update.\\n\\n\" +\n              `removing illegal node: \"${(childNode.outerHTML || childNode.nodeValue).trim()}\"\\n\\n`)\n          }\n          toRemove.push(childNode)\n        }\n      })\n      toRemove.forEach(childNode => childNode.remove())\n    }\n  },\n\n  replaceRootContainer(container, tagName, attrs){\n    let retainedAttrs = new Set([\"id\", PHX_SESSION, PHX_STATIC, PHX_MAIN, PHX_ROOT_ID])\n    if(container.tagName.toLowerCase() === tagName.toLowerCase()){\n      Array.from(container.attributes)\n        .filter(attr => !retainedAttrs.has(attr.name.toLowerCase()))\n        .forEach(attr => container.removeAttribute(attr.name))\n\n      Object.keys(attrs)\n        .filter(name => !retainedAttrs.has(name.toLowerCase()))\n        .forEach(attr => container.setAttribute(attr, attrs[attr]))\n\n      return container\n\n    } else {\n      let newContainer = document.createElement(tagName)\n      Object.keys(attrs).forEach(attr => newContainer.setAttribute(attr, attrs[attr]))\n      retainedAttrs.forEach(attr => newContainer.setAttribute(attr, container.getAttribute(attr)))\n      newContainer.innerHTML = container.innerHTML\n      container.replaceWith(newContainer)\n      return newContainer\n    }\n  },\n\n  getSticky(el, name, defaultVal){\n    let op = (DOM.private(el, \"sticky\") || []).find(([existingName, ]) => name === existingName)\n    if(op){\n      let [_name, _op, stashedResult] = op\n      return stashedResult\n    } else {\n      return typeof(defaultVal) === \"function\" ? defaultVal() : defaultVal\n    }\n  },\n\n  deleteSticky(el, name){\n    this.updatePrivate(el, \"sticky\", [], ops => {\n      return ops.filter(([existingName, _]) => existingName !== name)\n    })\n  },\n\n  putSticky(el, name, op){\n    let stashedResult = op(el)\n    this.updatePrivate(el, \"sticky\", [], ops => {\n      let existingIndex = ops.findIndex(([existingName, ]) => name === existingName)\n      if(existingIndex >= 0){\n        ops[existingIndex] = [name, op, stashedResult]\n      } else {\n        ops.push([name, op, stashedResult])\n      }\n      return ops\n    })\n  },\n\n  applyStickyOperations(el){\n    let ops = DOM.private(el, \"sticky\")\n    if(!ops){ return }\n\n    ops.forEach(([name, op, _stashed]) => this.putSticky(el, name, op))\n  }\n}\n\nexport default DOM\n", "import {\n  PHX_ACTIVE_ENTRY_REFS,\n  PHX_LIVE_FILE_UPDATED,\n  PHX_PREFLIGHTED_REFS\n} from \"./constants\"\n\nimport {\n  channelUploader,\n  logError\n} from \"./utils\"\n\nimport LiveUploader from \"./live_uploader\"\n\nexport default class UploadEntry {\n  static isActive(fileEl, file){\n    let isNew = file._phxRef === undefined\n    let activeRefs = fileEl.getAttribute(PHX_ACTIVE_ENTRY_REFS).split(\",\")\n    let isActive = activeRefs.indexOf(LiveUploader.genFileRef(file)) >= 0\n    return file.size > 0 && (isNew || isActive)\n  }\n\n  static isPreflighted(fileEl, file){\n    let preflightedRefs = fileEl.getAttribute(PHX_PREFLIGHTED_REFS).split(\",\")\n    let isPreflighted = preflightedRefs.indexOf(LiveUploader.genFileRef(file)) >= 0\n    return isPreflighted && this.isActive(fileEl, file)\n  }\n\n  constructor(fileEl, file, view){\n    this.ref = LiveUploader.genFileRef(file)\n    this.fileEl = fileEl\n    this.file = file\n    this.view = view\n    this.meta = null\n    this._isCancelled = false\n    this._isDone = false\n    this._progress = 0\n    this._lastProgressSent = -1\n    this._onDone = function (){ }\n    this._onElUpdated = this.onElUpdated.bind(this)\n    this.fileEl.addEventListener(PHX_LIVE_FILE_UPDATED, this._onElUpdated)\n  }\n\n  metadata(){ return this.meta }\n\n  progress(progress){\n    this._progress = Math.floor(progress)\n    if(this._progress > this._lastProgressSent){\n      if(this._progress >= 100){\n        this._progress = 100\n        this._lastProgressSent = 100\n        this._isDone = true\n        this.view.pushFileProgress(this.fileEl, this.ref, 100, () => {\n          LiveUploader.untrackFile(this.fileEl, this.file)\n          this._onDone()\n        })\n      } else {\n        this._lastProgressSent = this._progress\n        this.view.pushFileProgress(this.fileEl, this.ref, this._progress)\n      }\n    }\n  }\n\n  cancel(){\n    this._isCancelled = true\n    this._isDone = true\n    this._onDone()\n  }\n\n  isDone(){ return this._isDone }\n\n  error(reason = \"failed\"){\n    this.view.pushFileProgress(this.fileEl, this.ref, {error: reason})\n    LiveUploader.clearFiles(this.fileEl)\n  }\n\n  //private\n\n  onDone(callback){\n    this._onDone = () => {\n      this.fileEl.removeEventListener(PHX_LIVE_FILE_UPDATED, this._onElUpdated)\n      callback()\n    }\n  }\n\n  onElUpdated(){\n    let activeRefs = this.fileEl.getAttribute(PHX_ACTIVE_ENTRY_REFS).split(\",\")\n    if(activeRefs.indexOf(this.ref) === -1){ this.cancel() }\n  }\n\n  toPreflightPayload(){\n    return {\n      last_modified: this.file.lastModified,\n      name: this.file.name,\n      size: this.file.size,\n      type: this.file.type,\n      ref: this.ref\n    }\n  }\n\n  uploader(uploaders){\n    if(this.meta.uploader){\n      let callback = uploaders[this.meta.uploader] || logError(`no uploader configured for ${this.meta.uploader}`)\n      return {name: this.meta.uploader, callback: callback}\n    } else {\n      return {name: \"channel\", callback: channelUploader}\n    }\n  }\n\n  zipPostFlight(resp){\n    this.meta = resp.entries[this.ref]\n    if(!this.meta){ logError(`no preflight upload response returned with ref ${this.ref}`, {input: this.fileEl, response: resp}) }\n  }\n}\n", "import {\n  PHX_DONE_REFS,\n  PHX_PREFLIGHTED_REFS,\n  PHX_UPLOAD_REF\n} from \"./constants\"\n\nimport {\n} from \"./utils\"\n\nimport DOM from \"./dom\"\nimport UploadEntry from \"./upload_entry\"\n\nlet liveUploaderFileRef = 0\n\nexport default class LiveUploader {\n  static genFileRef(file){\n    let ref = file._phxRef\n    if(ref !== undefined){\n      return ref\n    } else {\n      file._phxRef = (liveUploaderFileRef++).toString()\n      return file._phxRef\n    }\n  }\n\n  static getEntryDataURL(inputEl, ref, callback){\n    let file = this.activeFiles(inputEl).find(file => this.genFileRef(file) === ref)\n    callback(URL.createObjectURL(file))\n  }\n\n  static hasUploadsInProgress(formEl){\n    let active = 0\n    DOM.findUploadInputs(formEl).forEach(input => {\n      if(input.getAttribute(PHX_PREFLIGHTED_REFS) !== input.getAttribute(PHX_DONE_REFS)){\n        active++\n      }\n    })\n    return active > 0\n  }\n\n  static serializeUploads(inputEl){\n    let files = this.activeFiles(inputEl)\n    let fileData = {}\n    files.forEach(file => {\n      let entry = {path: inputEl.name}\n      let uploadRef = inputEl.getAttribute(PHX_UPLOAD_REF)\n      fileData[uploadRef] = fileData[uploadRef] || []\n      entry.ref = this.genFileRef(file)\n      entry.name = file.name || entry.ref\n      entry.type = file.type\n      entry.size = file.size\n      fileData[uploadRef].push(entry)\n    })\n    return fileData\n  }\n\n  static clearFiles(inputEl){\n    inputEl.value = null\n    inputEl.removeAttribute(PHX_UPLOAD_REF)\n    DOM.putPrivate(inputEl, \"files\", [])\n  }\n\n  static untrackFile(inputEl, file){\n    DOM.putPrivate(inputEl, \"files\", DOM.private(inputEl, \"files\").filter(f => !Object.is(f, file)))\n  }\n\n  static trackFiles(inputEl, files){\n    if(inputEl.getAttribute(\"multiple\") !== null){\n      let newFiles = files.filter(file => !this.activeFiles(inputEl).find(f => Object.is(f, file)))\n      DOM.putPrivate(inputEl, \"files\", this.activeFiles(inputEl).concat(newFiles))\n      inputEl.value = null\n    } else {\n      DOM.putPrivate(inputEl, \"files\", files)\n    }\n  }\n\n  static activeFileInputs(formEl){\n    let fileInputs = DOM.findUploadInputs(formEl)\n    return Array.from(fileInputs).filter(el => el.files && this.activeFiles(el).length > 0)\n  }\n\n  static activeFiles(input){\n    return (DOM.private(input, \"files\") || []).filter(f => UploadEntry.isActive(input, f))\n  }\n\n  static inputsAwaitingPreflight(formEl){\n    let fileInputs = DOM.findUploadInputs(formEl)\n    return Array.from(fileInputs).filter(input => this.filesAwaitingPreflight(input).length > 0)\n  }\n\n  static filesAwaitingPreflight(input){\n    return this.activeFiles(input).filter(f => !UploadEntry.isPreflighted(input, f))\n  }\n\n  constructor(inputEl, view, onComplete){\n    this.view = view\n    this.onComplete = onComplete\n    this._entries =\n      Array.from(LiveUploader.filesAwaitingPreflight(inputEl) || [])\n        .map(file => new UploadEntry(inputEl, file, view))\n\n    this.numEntriesInProgress = this._entries.length\n  }\n\n  entries(){ return this._entries }\n\n  initAdapterUpload(resp, onError, liveSocket){\n    this._entries =\n      this._entries.map(entry => {\n        entry.zipPostFlight(resp)\n        entry.onDone(() => {\n          this.numEntriesInProgress--\n          if(this.numEntriesInProgress === 0){ this.onComplete() }\n        })\n        return entry\n      })\n\n    let groupedEntries = this._entries.reduce((acc, entry) => {\n      let {name, callback} = entry.uploader(liveSocket.uploaders)\n      acc[name] = acc[name] || {callback: callback, entries: []}\n      acc[name].entries.push(entry)\n      return acc\n    }, {})\n\n    for(let name in groupedEntries){\n      let {callback, entries} = groupedEntries[name]\n      callback(entries, onError, resp, liveSocket)\n    }\n  }\n}\n", "import {\n  PHX_ACTIVE_ENTRY_REFS,\n  PHX_LIVE_FILE_UPDATED,\n  PHX_PREFLIGHTED_REFS,\n  PHX_UPLOAD_REF\n} from \"./constants\"\n\nimport LiveUploader from \"./live_uploader\"\n\nlet Hooks = {\n  LiveFileUpload: {\n    activeRefs(){ return this.el.getAttribute(PHX_ACTIVE_ENTRY_REFS) },\n\n    preflightedRefs(){ return this.el.getAttribute(PHX_PREFLIGHTED_REFS) },\n\n    mounted(){ this.preflightedWas = this.preflightedRefs() },\n\n    updated(){\n      let newPreflights = this.preflightedRefs()\n      if(this.preflightedWas !== newPreflights){\n        this.preflightedWas = newPreflights\n        if(newPreflights === \"\"){\n          this.__view.cancelSubmit(this.el.form)\n        }\n      }\n\n      if(this.activeRefs() === \"\"){ this.el.value = null }\n      this.el.dispatchEvent(new CustomEvent(PHX_LIVE_FILE_UPDATED))\n    }\n  },\n\n  LiveImgPreview: {\n    mounted(){\n      this.ref = this.el.getAttribute(\"data-phx-entry-ref\")\n      this.inputEl = document.getElementById(this.el.getAttribute(PHX_UPLOAD_REF))\n      LiveUploader.getEntryDataURL(this.inputEl, this.ref, url => {\n        this.url = url\n        this.el.src = url\n      })\n    },\n    destroyed(){\n      URL.revokeObjectURL(this.url)\n    }\n  }\n}\n\nexport default Hooks\n", "import {\n  maybe\n} from \"./utils\"\n\nimport DOM from \"./dom\"\n\nexport default class DOMPostMorphRestorer {\n  constructor(containerBefore, containerAfter, updateType){\n    let idsBefore = new Set()\n    let idsAfter = new Set([...containerAfter.children].map(child => child.id))\n\n    let elementsToModify = []\n\n    Array.from(containerBefore.children).forEach(child => {\n      if(child.id){ // all of our children should be elements with ids\n        idsBefore.add(child.id)\n        if(idsAfter.has(child.id)){\n          let previousElementId = child.previousElementSibling && child.previousElementSibling.id\n          elementsToModify.push({elementId: child.id, previousElementId: previousElementId})\n        }\n      }\n    })\n\n    this.containerId = containerAfter.id\n    this.updateType = updateType\n    this.elementsToModify = elementsToModify\n    this.elementIdsToAdd = [...idsAfter].filter(id => !idsBefore.has(id))\n  }\n\n  // We do the following to optimize append/prepend operations:\n  //   1) Track ids of modified elements & of new elements\n  //   2) All the modified elements are put back in the correct position in the DOM tree\n  //      by storing the id of their previous sibling\n  //   3) New elements are going to be put in the right place by morphdom during append.\n  //      For prepend, we move them to the first position in the container\n  perform(){\n    let container = DOM.byId(this.containerId)\n    this.elementsToModify.forEach(elementToModify => {\n      if(elementToModify.previousElementId){\n        maybe(document.getElementById(elementToModify.previousElementId), previousElem => {\n          maybe(document.getElementById(elementToModify.elementId), elem => {\n            let isInRightPlace = elem.previousElementSibling && elem.previousElementSibling.id == previousElem.id\n            if(!isInRightPlace){\n              previousElem.insertAdjacentElement(\"afterend\", elem)\n            }\n          })\n        })\n      } else {\n        // This is the first element in the container\n        maybe(document.getElementById(elementToModify.elementId), elem => {\n          let isInRightPlace = elem.previousElementSibling == null\n          if(!isInRightPlace){\n            container.insertAdjacentElement(\"afterbegin\", elem)\n          }\n        })\n      }\n    })\n\n    if(this.updateType == \"prepend\"){\n      this.elementIdsToAdd.reverse().forEach(elemId => {\n        maybe(document.getElementById(elemId), elem => container.insertAdjacentElement(\"afterbegin\", elem))\n      })\n    }\n  }\n}\n", "var DOCUMENT_FRAGMENT_NODE = 11;\n\nfunction morphAttrs(fromNode, toNode) {\n    var toNodeAttrs = toNode.attributes;\n    var attr;\n    var attrName;\n    var attrNamespaceURI;\n    var attrValue;\n    var fromValue;\n\n    // document-fragments dont have attributes so lets not do anything\n    if (toNode.nodeType === DOCUMENT_FRAGMENT_NODE || fromNode.nodeType === DOCUMENT_FRAGMENT_NODE) {\n      return;\n    }\n\n    // update attributes on original DOM element\n    for (var i = toNodeAttrs.length - 1; i >= 0; i--) {\n        attr = toNodeAttrs[i];\n        attrName = attr.name;\n        attrNamespaceURI = attr.namespaceURI;\n        attrValue = attr.value;\n\n        if (attrNamespaceURI) {\n            attrName = attr.localName || attrName;\n            fromValue = fromNode.getAttributeNS(attrNamespaceURI, attrName);\n\n            if (fromValue !== attrValue) {\n                if (attr.prefix === 'xmlns'){\n                    attrName = attr.name; // It's not allowed to set an attribute with the XMLNS namespace without specifying the `xmlns` prefix\n                }\n                fromNode.setAttributeNS(attrNamespaceURI, attrName, attrValue);\n            }\n        } else {\n            fromValue = fromNode.getAttribute(attrName);\n\n            if (fromValue !== attrValue) {\n                fromNode.setAttribute(attrName, attrValue);\n            }\n        }\n    }\n\n    // Remove any extra attributes found on the original DOM element that\n    // weren't found on the target element.\n    var fromNodeAttrs = fromNode.attributes;\n\n    for (var d = fromNodeAttrs.length - 1; d >= 0; d--) {\n        attr = fromNodeAttrs[d];\n        attrName = attr.name;\n        attrNamespaceURI = attr.namespaceURI;\n\n        if (attrNamespaceURI) {\n            attrName = attr.localName || attrName;\n\n            if (!toNode.hasAttributeNS(attrNamespaceURI, attrName)) {\n                fromNode.removeAttributeNS(attrNamespaceURI, attrName);\n            }\n        } else {\n            if (!toNode.hasAttribute(attrName)) {\n                fromNode.removeAttribute(attrName);\n            }\n        }\n    }\n}\n\nvar range; // Create a range object for efficently rendering strings to elements.\nvar NS_XHTML = 'http://www.w3.org/1999/xhtml';\n\nvar doc = typeof document === 'undefined' ? undefined : document;\nvar HAS_TEMPLATE_SUPPORT = !!doc && 'content' in doc.createElement('template');\nvar HAS_RANGE_SUPPORT = !!doc && doc.createRange && 'createContextualFragment' in doc.createRange();\n\nfunction createFragmentFromTemplate(str) {\n    var template = doc.createElement('template');\n    template.innerHTML = str;\n    return template.content.childNodes[0];\n}\n\nfunction createFragmentFromRange(str) {\n    if (!range) {\n        range = doc.createRange();\n        range.selectNode(doc.body);\n    }\n\n    var fragment = range.createContextualFragment(str);\n    return fragment.childNodes[0];\n}\n\nfunction createFragmentFromWrap(str) {\n    var fragment = doc.createElement('body');\n    fragment.innerHTML = str;\n    return fragment.childNodes[0];\n}\n\n/**\n * This is about the same\n * var html = new DOMParser().parseFromString(str, 'text/html');\n * return html.body.firstChild;\n *\n * @method toElement\n * @param {String} str\n */\nfunction toElement(str) {\n    str = str.trim();\n    if (HAS_TEMPLATE_SUPPORT) {\n      // avoid restrictions on content for things like `<tr><th>Hi</th></tr>` which\n      // createContextualFragment doesn't support\n      // <template> support not available in IE\n      return createFragmentFromTemplate(str);\n    } else if (HAS_RANGE_SUPPORT) {\n      return createFragmentFromRange(str);\n    }\n\n    return createFragmentFromWrap(str);\n}\n\n/**\n * Returns true if two node's names are the same.\n *\n * NOTE: We don't bother checking `namespaceURI` because you will never find two HTML elements with the same\n *       nodeName and different namespace URIs.\n *\n * @param {Element} a\n * @param {Element} b The target element\n * @return {boolean}\n */\nfunction compareNodeNames(fromEl, toEl) {\n    var fromNodeName = fromEl.nodeName;\n    var toNodeName = toEl.nodeName;\n    var fromCodeStart, toCodeStart;\n\n    if (fromNodeName === toNodeName) {\n        return true;\n    }\n\n    fromCodeStart = fromNodeName.charCodeAt(0);\n    toCodeStart = toNodeName.charCodeAt(0);\n\n    // If the target element is a virtual DOM node or SVG node then we may\n    // need to normalize the tag name before comparing. Normal HTML elements that are\n    // in the \"http://www.w3.org/1999/xhtml\"\n    // are converted to upper case\n    if (fromCodeStart <= 90 && toCodeStart >= 97) { // from is upper and to is lower\n        return fromNodeName === toNodeName.toUpperCase();\n    } else if (toCodeStart <= 90 && fromCodeStart >= 97) { // to is upper and from is lower\n        return toNodeName === fromNodeName.toUpperCase();\n    } else {\n        return false;\n    }\n}\n\n/**\n * Create an element, optionally with a known namespace URI.\n *\n * @param {string} name the element name, e.g. 'div' or 'svg'\n * @param {string} [namespaceURI] the element's namespace URI, i.e. the value of\n * its `xmlns` attribute or its inferred namespace.\n *\n * @return {Element}\n */\nfunction createElementNS(name, namespaceURI) {\n    return !namespaceURI || namespaceURI === NS_XHTML ?\n        doc.createElement(name) :\n        doc.createElementNS(namespaceURI, name);\n}\n\n/**\n * Copies the children of one DOM element to another DOM element\n */\nfunction moveChildren(fromEl, toEl) {\n    var curChild = fromEl.firstChild;\n    while (curChild) {\n        var nextChild = curChild.nextSibling;\n        toEl.appendChild(curChild);\n        curChild = nextChild;\n    }\n    return toEl;\n}\n\nfunction syncBooleanAttrProp(fromEl, toEl, name) {\n    if (fromEl[name] !== toEl[name]) {\n        fromEl[name] = toEl[name];\n        if (fromEl[name]) {\n            fromEl.setAttribute(name, '');\n        } else {\n            fromEl.removeAttribute(name);\n        }\n    }\n}\n\nvar specialElHandlers = {\n    OPTION: function(fromEl, toEl) {\n        var parentNode = fromEl.parentNode;\n        if (parentNode) {\n            var parentName = parentNode.nodeName.toUpperCase();\n            if (parentName === 'OPTGROUP') {\n                parentNode = parentNode.parentNode;\n                parentName = parentNode && parentNode.nodeName.toUpperCase();\n            }\n            if (parentName === 'SELECT' && !parentNode.hasAttribute('multiple')) {\n                if (fromEl.hasAttribute('selected') && !toEl.selected) {\n                    // Workaround for MS Edge bug where the 'selected' attribute can only be\n                    // removed if set to a non-empty value:\n                    // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/12087679/\n                    fromEl.setAttribute('selected', 'selected');\n                    fromEl.removeAttribute('selected');\n                }\n                // We have to reset select element's selectedIndex to -1, otherwise setting\n                // fromEl.selected using the syncBooleanAttrProp below has no effect.\n                // The correct selectedIndex will be set in the SELECT special handler below.\n                parentNode.selectedIndex = -1;\n            }\n        }\n        syncBooleanAttrProp(fromEl, toEl, 'selected');\n    },\n    /**\n     * The \"value\" attribute is special for the <input> element since it sets\n     * the initial value. Changing the \"value\" attribute without changing the\n     * \"value\" property will have no effect since it is only used to the set the\n     * initial value.  Similar for the \"checked\" attribute, and \"disabled\".\n     */\n    INPUT: function(fromEl, toEl) {\n        syncBooleanAttrProp(fromEl, toEl, 'checked');\n        syncBooleanAttrProp(fromEl, toEl, 'disabled');\n\n        if (fromEl.value !== toEl.value) {\n            fromEl.value = toEl.value;\n        }\n\n        if (!toEl.hasAttribute('value')) {\n            fromEl.removeAttribute('value');\n        }\n    },\n\n    TEXTAREA: function(fromEl, toEl) {\n        var newValue = toEl.value;\n        if (fromEl.value !== newValue) {\n            fromEl.value = newValue;\n        }\n\n        var firstChild = fromEl.firstChild;\n        if (firstChild) {\n            // Needed for IE. Apparently IE sets the placeholder as the\n            // node value and vise versa. This ignores an empty update.\n            var oldValue = firstChild.nodeValue;\n\n            if (oldValue == newValue || (!newValue && oldValue == fromEl.placeholder)) {\n                return;\n            }\n\n            firstChild.nodeValue = newValue;\n        }\n    },\n    SELECT: function(fromEl, toEl) {\n        if (!toEl.hasAttribute('multiple')) {\n            var selectedIndex = -1;\n            var i = 0;\n            // We have to loop through children of fromEl, not toEl since nodes can be moved\n            // from toEl to fromEl directly when morphing.\n            // At the time this special handler is invoked, all children have already been morphed\n            // and appended to / removed from fromEl, so using fromEl here is safe and correct.\n            var curChild = fromEl.firstChild;\n            var optgroup;\n            var nodeName;\n            while(curChild) {\n                nodeName = curChild.nodeName && curChild.nodeName.toUpperCase();\n                if (nodeName === 'OPTGROUP') {\n                    optgroup = curChild;\n                    curChild = optgroup.firstChild;\n                } else {\n                    if (nodeName === 'OPTION') {\n                        if (curChild.hasAttribute('selected')) {\n                            selectedIndex = i;\n                            break;\n                        }\n                        i++;\n                    }\n                    curChild = curChild.nextSibling;\n                    if (!curChild && optgroup) {\n                        curChild = optgroup.nextSibling;\n                        optgroup = null;\n                    }\n                }\n            }\n\n            fromEl.selectedIndex = selectedIndex;\n        }\n    }\n};\n\nvar ELEMENT_NODE = 1;\nvar DOCUMENT_FRAGMENT_NODE$1 = 11;\nvar TEXT_NODE = 3;\nvar COMMENT_NODE = 8;\n\nfunction noop() {}\n\nfunction defaultGetNodeKey(node) {\n  if (node) {\n      return (node.getAttribute && node.getAttribute('id')) || node.id;\n  }\n}\n\nfunction morphdomFactory(morphAttrs) {\n\n    return function morphdom(fromNode, toNode, options) {\n        if (!options) {\n            options = {};\n        }\n\n        if (typeof toNode === 'string') {\n            if (fromNode.nodeName === '#document' || fromNode.nodeName === 'HTML' || fromNode.nodeName === 'BODY') {\n                var toNodeHtml = toNode;\n                toNode = doc.createElement('html');\n                toNode.innerHTML = toNodeHtml;\n            } else {\n                toNode = toElement(toNode);\n            }\n        }\n\n        var getNodeKey = options.getNodeKey || defaultGetNodeKey;\n        var onBeforeNodeAdded = options.onBeforeNodeAdded || noop;\n        var onNodeAdded = options.onNodeAdded || noop;\n        var onBeforeElUpdated = options.onBeforeElUpdated || noop;\n        var onElUpdated = options.onElUpdated || noop;\n        var onBeforeNodeDiscarded = options.onBeforeNodeDiscarded || noop;\n        var onNodeDiscarded = options.onNodeDiscarded || noop;\n        var onBeforeElChildrenUpdated = options.onBeforeElChildrenUpdated || noop;\n        var childrenOnly = options.childrenOnly === true;\n\n        // This object is used as a lookup to quickly find all keyed elements in the original DOM tree.\n        var fromNodesLookup = Object.create(null);\n        var keyedRemovalList = [];\n\n        function addKeyedRemoval(key) {\n            keyedRemovalList.push(key);\n        }\n\n        function walkDiscardedChildNodes(node, skipKeyedNodes) {\n            if (node.nodeType === ELEMENT_NODE) {\n                var curChild = node.firstChild;\n                while (curChild) {\n\n                    var key = undefined;\n\n                    if (skipKeyedNodes && (key = getNodeKey(curChild))) {\n                        // If we are skipping keyed nodes then we add the key\n                        // to a list so that it can be handled at the very end.\n                        addKeyedRemoval(key);\n                    } else {\n                        // Only report the node as discarded if it is not keyed. We do this because\n                        // at the end we loop through all keyed elements that were unmatched\n                        // and then discard them in one final pass.\n                        onNodeDiscarded(curChild);\n                        if (curChild.firstChild) {\n                            walkDiscardedChildNodes(curChild, skipKeyedNodes);\n                        }\n                    }\n\n                    curChild = curChild.nextSibling;\n                }\n            }\n        }\n\n        /**\n         * Removes a DOM node out of the original DOM\n         *\n         * @param  {Node} node The node to remove\n         * @param  {Node} parentNode The nodes parent\n         * @param  {Boolean} skipKeyedNodes If true then elements with keys will be skipped and not discarded.\n         * @return {undefined}\n         */\n        function removeNode(node, parentNode, skipKeyedNodes) {\n            if (onBeforeNodeDiscarded(node) === false) {\n                return;\n            }\n\n            if (parentNode) {\n                parentNode.removeChild(node);\n            }\n\n            onNodeDiscarded(node);\n            walkDiscardedChildNodes(node, skipKeyedNodes);\n        }\n\n        // // TreeWalker implementation is no faster, but keeping this around in case this changes in the future\n        // function indexTree(root) {\n        //     var treeWalker = document.createTreeWalker(\n        //         root,\n        //         NodeFilter.SHOW_ELEMENT);\n        //\n        //     var el;\n        //     while((el = treeWalker.nextNode())) {\n        //         var key = getNodeKey(el);\n        //         if (key) {\n        //             fromNodesLookup[key] = el;\n        //         }\n        //     }\n        // }\n\n        // // NodeIterator implementation is no faster, but keeping this around in case this changes in the future\n        //\n        // function indexTree(node) {\n        //     var nodeIterator = document.createNodeIterator(node, NodeFilter.SHOW_ELEMENT);\n        //     var el;\n        //     while((el = nodeIterator.nextNode())) {\n        //         var key = getNodeKey(el);\n        //         if (key) {\n        //             fromNodesLookup[key] = el;\n        //         }\n        //     }\n        // }\n\n        function indexTree(node) {\n            if (node.nodeType === ELEMENT_NODE || node.nodeType === DOCUMENT_FRAGMENT_NODE$1) {\n                var curChild = node.firstChild;\n                while (curChild) {\n                    var key = getNodeKey(curChild);\n                    if (key) {\n                        fromNodesLookup[key] = curChild;\n                    }\n\n                    // Walk recursively\n                    indexTree(curChild);\n\n                    curChild = curChild.nextSibling;\n                }\n            }\n        }\n\n        indexTree(fromNode);\n\n        function handleNodeAdded(el) {\n            onNodeAdded(el);\n\n            var curChild = el.firstChild;\n            while (curChild) {\n                var nextSibling = curChild.nextSibling;\n\n                var key = getNodeKey(curChild);\n                if (key) {\n                    var unmatchedFromEl = fromNodesLookup[key];\n                    // if we find a duplicate #id node in cache, replace `el` with cache value\n                    // and morph it to the child node.\n                    if (unmatchedFromEl && compareNodeNames(curChild, unmatchedFromEl)) {\n                        curChild.parentNode.replaceChild(unmatchedFromEl, curChild);\n                        morphEl(unmatchedFromEl, curChild);\n                    } else {\n                      handleNodeAdded(curChild);\n                    }\n                } else {\n                  // recursively call for curChild and it's children to see if we find something in\n                  // fromNodesLookup\n                  handleNodeAdded(curChild);\n                }\n\n                curChild = nextSibling;\n            }\n        }\n\n        function cleanupFromEl(fromEl, curFromNodeChild, curFromNodeKey) {\n            // We have processed all of the \"to nodes\". If curFromNodeChild is\n            // non-null then we still have some from nodes left over that need\n            // to be removed\n            while (curFromNodeChild) {\n                var fromNextSibling = curFromNodeChild.nextSibling;\n                if ((curFromNodeKey = getNodeKey(curFromNodeChild))) {\n                    // Since the node is keyed it might be matched up later so we defer\n                    // the actual removal to later\n                    addKeyedRemoval(curFromNodeKey);\n                } else {\n                    // NOTE: we skip nested keyed nodes from being removed since there is\n                    //       still a chance they will be matched up later\n                    removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */);\n                }\n                curFromNodeChild = fromNextSibling;\n            }\n        }\n\n        function morphEl(fromEl, toEl, childrenOnly) {\n            var toElKey = getNodeKey(toEl);\n\n            if (toElKey) {\n                // If an element with an ID is being morphed then it will be in the final\n                // DOM so clear it out of the saved elements collection\n                delete fromNodesLookup[toElKey];\n            }\n\n            if (!childrenOnly) {\n                // optional\n                if (onBeforeElUpdated(fromEl, toEl) === false) {\n                    return;\n                }\n\n                // update attributes on original DOM element first\n                morphAttrs(fromEl, toEl);\n                // optional\n                onElUpdated(fromEl);\n\n                if (onBeforeElChildrenUpdated(fromEl, toEl) === false) {\n                    return;\n                }\n            }\n\n            if (fromEl.nodeName !== 'TEXTAREA') {\n              morphChildren(fromEl, toEl);\n            } else {\n              specialElHandlers.TEXTAREA(fromEl, toEl);\n            }\n        }\n\n        function morphChildren(fromEl, toEl) {\n            var curToNodeChild = toEl.firstChild;\n            var curFromNodeChild = fromEl.firstChild;\n            var curToNodeKey;\n            var curFromNodeKey;\n\n            var fromNextSibling;\n            var toNextSibling;\n            var matchingFromEl;\n\n            // walk the children\n            outer: while (curToNodeChild) {\n                toNextSibling = curToNodeChild.nextSibling;\n                curToNodeKey = getNodeKey(curToNodeChild);\n\n                // walk the fromNode children all the way through\n                while (curFromNodeChild) {\n                    fromNextSibling = curFromNodeChild.nextSibling;\n\n                    if (curToNodeChild.isSameNode && curToNodeChild.isSameNode(curFromNodeChild)) {\n                        curToNodeChild = toNextSibling;\n                        curFromNodeChild = fromNextSibling;\n                        continue outer;\n                    }\n\n                    curFromNodeKey = getNodeKey(curFromNodeChild);\n\n                    var curFromNodeType = curFromNodeChild.nodeType;\n\n                    // this means if the curFromNodeChild doesnt have a match with the curToNodeChild\n                    var isCompatible = undefined;\n\n                    if (curFromNodeType === curToNodeChild.nodeType) {\n                        if (curFromNodeType === ELEMENT_NODE) {\n                            // Both nodes being compared are Element nodes\n\n                            if (curToNodeKey) {\n                                // The target node has a key so we want to match it up with the correct element\n                                // in the original DOM tree\n                                if (curToNodeKey !== curFromNodeKey) {\n                                    // The current element in the original DOM tree does not have a matching key so\n                                    // let's check our lookup to see if there is a matching element in the original\n                                    // DOM tree\n                                    if ((matchingFromEl = fromNodesLookup[curToNodeKey])) {\n                                        if (fromNextSibling === matchingFromEl) {\n                                            // Special case for single element removals. To avoid removing the original\n                                            // DOM node out of the tree (since that can break CSS transitions, etc.),\n                                            // we will instead discard the current node and wait until the next\n                                            // iteration to properly match up the keyed target element with its matching\n                                            // element in the original tree\n                                            isCompatible = false;\n                                        } else {\n                                            // We found a matching keyed element somewhere in the original DOM tree.\n                                            // Let's move the original DOM node into the current position and morph\n                                            // it.\n\n                                            // NOTE: We use insertBefore instead of replaceChild because we want to go through\n                                            // the `removeNode()` function for the node that is being discarded so that\n                                            // all lifecycle hooks are correctly invoked\n                                            fromEl.insertBefore(matchingFromEl, curFromNodeChild);\n\n                                            // fromNextSibling = curFromNodeChild.nextSibling;\n\n                                            if (curFromNodeKey) {\n                                                // Since the node is keyed it might be matched up later so we defer\n                                                // the actual removal to later\n                                                addKeyedRemoval(curFromNodeKey);\n                                            } else {\n                                                // NOTE: we skip nested keyed nodes from being removed since there is\n                                                //       still a chance they will be matched up later\n                                                removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */);\n                                            }\n\n                                            curFromNodeChild = matchingFromEl;\n                                        }\n                                    } else {\n                                        // The nodes are not compatible since the \"to\" node has a key and there\n                                        // is no matching keyed node in the source tree\n                                        isCompatible = false;\n                                    }\n                                }\n                            } else if (curFromNodeKey) {\n                                // The original has a key\n                                isCompatible = false;\n                            }\n\n                            isCompatible = isCompatible !== false && compareNodeNames(curFromNodeChild, curToNodeChild);\n                            if (isCompatible) {\n                                // We found compatible DOM elements so transform\n                                // the current \"from\" node to match the current\n                                // target DOM node.\n                                // MORPH\n                                morphEl(curFromNodeChild, curToNodeChild);\n                            }\n\n                        } else if (curFromNodeType === TEXT_NODE || curFromNodeType == COMMENT_NODE) {\n                            // Both nodes being compared are Text or Comment nodes\n                            isCompatible = true;\n                            // Simply update nodeValue on the original node to\n                            // change the text value\n                            if (curFromNodeChild.nodeValue !== curToNodeChild.nodeValue) {\n                                curFromNodeChild.nodeValue = curToNodeChild.nodeValue;\n                            }\n\n                        }\n                    }\n\n                    if (isCompatible) {\n                        // Advance both the \"to\" child and the \"from\" child since we found a match\n                        // Nothing else to do as we already recursively called morphChildren above\n                        curToNodeChild = toNextSibling;\n                        curFromNodeChild = fromNextSibling;\n                        continue outer;\n                    }\n\n                    // No compatible match so remove the old node from the DOM and continue trying to find a\n                    // match in the original DOM. However, we only do this if the from node is not keyed\n                    // since it is possible that a keyed node might match up with a node somewhere else in the\n                    // target tree and we don't want to discard it just yet since it still might find a\n                    // home in the final DOM tree. After everything is done we will remove any keyed nodes\n                    // that didn't find a home\n                    if (curFromNodeKey) {\n                        // Since the node is keyed it might be matched up later so we defer\n                        // the actual removal to later\n                        addKeyedRemoval(curFromNodeKey);\n                    } else {\n                        // NOTE: we skip nested keyed nodes from being removed since there is\n                        //       still a chance they will be matched up later\n                        removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */);\n                    }\n\n                    curFromNodeChild = fromNextSibling;\n                } // END: while(curFromNodeChild) {}\n\n                // If we got this far then we did not find a candidate match for\n                // our \"to node\" and we exhausted all of the children \"from\"\n                // nodes. Therefore, we will just append the current \"to\" node\n                // to the end\n                if (curToNodeKey && (matchingFromEl = fromNodesLookup[curToNodeKey]) && compareNodeNames(matchingFromEl, curToNodeChild)) {\n                    fromEl.appendChild(matchingFromEl);\n                    // MORPH\n                    morphEl(matchingFromEl, curToNodeChild);\n                } else {\n                    var onBeforeNodeAddedResult = onBeforeNodeAdded(curToNodeChild);\n                    if (onBeforeNodeAddedResult !== false) {\n                        if (onBeforeNodeAddedResult) {\n                            curToNodeChild = onBeforeNodeAddedResult;\n                        }\n\n                        if (curToNodeChild.actualize) {\n                            curToNodeChild = curToNodeChild.actualize(fromEl.ownerDocument || doc);\n                        }\n                        fromEl.appendChild(curToNodeChild);\n                        handleNodeAdded(curToNodeChild);\n                    }\n                }\n\n                curToNodeChild = toNextSibling;\n                curFromNodeChild = fromNextSibling;\n            }\n\n            cleanupFromEl(fromEl, curFromNodeChild, curFromNodeKey);\n\n            var specialElHandler = specialElHandlers[fromEl.nodeName];\n            if (specialElHandler) {\n                specialElHandler(fromEl, toEl);\n            }\n        } // END: morphChildren(...)\n\n        var morphedNode = fromNode;\n        var morphedNodeType = morphedNode.nodeType;\n        var toNodeType = toNode.nodeType;\n\n        if (!childrenOnly) {\n            // Handle the case where we are given two DOM nodes that are not\n            // compatible (e.g. <div> --> <span> or <div> --> TEXT)\n            if (morphedNodeType === ELEMENT_NODE) {\n                if (toNodeType === ELEMENT_NODE) {\n                    if (!compareNodeNames(fromNode, toNode)) {\n                        onNodeDiscarded(fromNode);\n                        morphedNode = moveChildren(fromNode, createElementNS(toNode.nodeName, toNode.namespaceURI));\n                    }\n                } else {\n                    // Going from an element node to a text node\n                    morphedNode = toNode;\n                }\n            } else if (morphedNodeType === TEXT_NODE || morphedNodeType === COMMENT_NODE) { // Text or comment node\n                if (toNodeType === morphedNodeType) {\n                    if (morphedNode.nodeValue !== toNode.nodeValue) {\n                        morphedNode.nodeValue = toNode.nodeValue;\n                    }\n\n                    return morphedNode;\n                } else {\n                    // Text node to something else\n                    morphedNode = toNode;\n                }\n            }\n        }\n\n        if (morphedNode === toNode) {\n            // The \"to node\" was not compatible with the \"from node\" so we had to\n            // toss out the \"from node\" and use the \"to node\"\n            onNodeDiscarded(fromNode);\n        } else {\n            if (toNode.isSameNode && toNode.isSameNode(morphedNode)) {\n                return;\n            }\n\n            morphEl(morphedNode, toNode, childrenOnly);\n\n            // We now need to loop over any keyed nodes that might need to be\n            // removed. We only do the removal if we know that the keyed node\n            // never found a match. When a keyed node is matched up we remove\n            // it out of fromNodesLookup and we use fromNodesLookup to determine\n            // if a keyed node has been matched up or not\n            if (keyedRemovalList) {\n                for (var i=0, len=keyedRemovalList.length; i<len; i++) {\n                    var elToRemove = fromNodesLookup[keyedRemovalList[i]];\n                    if (elToRemove) {\n                        removeNode(elToRemove, elToRemove.parentNode, false);\n                    }\n                }\n            }\n        }\n\n        if (!childrenOnly && morphedNode !== fromNode && fromNode.parentNode) {\n            if (morphedNode.actualize) {\n                morphedNode = morphedNode.actualize(fromNode.ownerDocument || doc);\n            }\n            // If we had to swap out the from node with a new node because the old\n            // node was not compatible with the target node then we need to\n            // replace the old DOM node in the original DOM tree. This is only\n            // possible if the original DOM node was part of a DOM tree which\n            // we know is the case if it has a parent node.\n            fromNode.parentNode.replaceChild(morphedNode, fromNode);\n        }\n\n        return morphedNode;\n    };\n}\n\nvar morphdom = morphdomFactory(morphAttrs);\n\nexport default morphdom;\n", "import {\n  PHX_COMPONENT,\n  PHX_DISABLE_WITH,\n  PHX_FEEDBACK_FOR,\n  PHX_PRUNE,\n  PHX_ROOT_ID,\n  PHX_SESSION,\n  PHX_SKIP,\n  PHX_STATIC,\n  PHX_TRIGGER_ACTION,\n  PHX_UPDATE\n} from \"./constants\"\n\nimport {\n  detectDuplicateIds,\n  isCid\n} from \"./utils\"\n\nimport DOM from \"./dom\"\nimport DOMPostMorphRestorer from \"./dom_post_morph_restorer\"\nimport morphdom from \"morphdom\"\n\nexport default class DOMPatch {\n  static patchEl(fromEl, toEl, activeElement){\n    morphdom(fromEl, toEl, {\n      childrenOnly: false,\n      onBeforeElUpdated: (fromEl, toEl) => {\n        if(activeElement && activeElement.isSameNode(fromEl) && DOM.isFormInput(fromEl)){\n          DOM.mergeFocusedInput(fromEl, toEl)\n          return false\n        }\n      }\n    })\n  }\n\n  constructor(view, container, id, html, targetCID){\n    this.view = view\n    this.liveSocket = view.liveSocket\n    this.container = container\n    this.id = id\n    this.rootID = view.root.id\n    this.html = html\n    this.targetCID = targetCID\n    this.cidPatch = isCid(this.targetCID)\n    this.callbacks = {\n      beforeadded: [], beforeupdated: [], beforephxChildAdded: [],\n      afteradded: [], afterupdated: [], afterdiscarded: [], afterphxChildAdded: [],\n      aftertransitionsDiscarded: []\n    }\n  }\n\n  before(kind, callback){ this.callbacks[`before${kind}`].push(callback) }\n  after(kind, callback){ this.callbacks[`after${kind}`].push(callback) }\n\n  trackBefore(kind, ...args){\n    this.callbacks[`before${kind}`].forEach(callback => callback(...args))\n  }\n\n  trackAfter(kind, ...args){\n    this.callbacks[`after${kind}`].forEach(callback => callback(...args))\n  }\n\n  markPrunableContentForRemoval(){\n    DOM.all(this.container, \"[phx-update=append] > *, [phx-update=prepend] > *\", el => {\n      el.setAttribute(PHX_PRUNE, \"\")\n    })\n  }\n\n  perform(){\n    let {view, liveSocket, container, html} = this\n    let targetContainer = this.isCIDPatch() ? this.targetCIDContainer(html) : container\n    if(this.isCIDPatch() && !targetContainer){ return }\n\n    let focused = liveSocket.getActiveElement()\n    let {selectionStart, selectionEnd} = focused && DOM.hasSelectionRange(focused) ? focused : {}\n    let phxUpdate = liveSocket.binding(PHX_UPDATE)\n    let phxFeedbackFor = liveSocket.binding(PHX_FEEDBACK_FOR)\n    let disableWith = liveSocket.binding(PHX_DISABLE_WITH)\n    let phxTriggerExternal = liveSocket.binding(PHX_TRIGGER_ACTION)\n    let phxRemove = liveSocket.binding(\"remove\")\n    let added = []\n    let updates = []\n    let appendPrependUpdates = []\n    let pendingRemoves = []\n    let externalFormTriggered = null\n\n    let diffHTML = liveSocket.time(\"premorph container prep\", () => {\n      return this.buildDiffHTML(container, html, phxUpdate, targetContainer)\n    })\n\n    this.trackBefore(\"added\", container)\n    this.trackBefore(\"updated\", container, container)\n\n    liveSocket.time(\"morphdom\", () => {\n      morphdom(targetContainer, diffHTML, {\n        childrenOnly: targetContainer.getAttribute(PHX_COMPONENT) === null,\n        getNodeKey: (node) => {\n          return DOM.isPhxDestroyed(node) ? null : node.id\n        },\n        onBeforeNodeAdded: (el) => {\n          this.trackBefore(\"added\", el)\n          return el\n        },\n        onNodeAdded: (el) => {\n          // hack to fix Safari handling of img srcset and video tags\n          if(el instanceof HTMLImageElement && el.srcset){\n            el.srcset = el.srcset\n          } else if(el instanceof HTMLVideoElement && el.autoplay){\n            el.play()\n          }\n          if(DOM.isNowTriggerFormExternal(el, phxTriggerExternal)){\n            externalFormTriggered = el\n          }\n          //input handling\n          DOM.discardError(targetContainer, el, phxFeedbackFor)\n          // nested view handling\n          if(DOM.isPhxChild(el) && view.ownsElement(el)){\n            this.trackAfter(\"phxChildAdded\", el)\n          }\n          added.push(el)\n        },\n        onNodeDiscarded: (el) => {\n          // nested view handling\n          if(DOM.isPhxChild(el)){ liveSocket.destroyViewByEl(el) }\n          this.trackAfter(\"discarded\", el)\n        },\n        onBeforeNodeDiscarded: (el) => {\n          if(el.getAttribute && el.getAttribute(PHX_PRUNE) !== null){ return true }\n          if(el.parentNode !== null && DOM.isPhxUpdate(el.parentNode, phxUpdate, [\"append\", \"prepend\"]) && el.id){ return false }\n          if(el.getAttribute && el.getAttribute(phxRemove)){\n            pendingRemoves.push(el)\n            return false\n          }\n          if(this.skipCIDSibling(el)){ return false }\n          return true\n        },\n        onElUpdated: (el) => {\n          if(DOM.isNowTriggerFormExternal(el, phxTriggerExternal)){\n            externalFormTriggered = el\n          }\n          updates.push(el)\n        },\n        onBeforeElUpdated: (fromEl, toEl) => {\n          DOM.cleanChildNodes(toEl, phxUpdate)\n          if(this.skipCIDSibling(toEl)){ return false }\n          if(DOM.isIgnored(fromEl, phxUpdate)){\n            this.trackBefore(\"updated\", fromEl, toEl)\n            DOM.mergeAttrs(fromEl, toEl, {isIgnored: true})\n            updates.push(fromEl)\n            DOM.applyStickyOperations(fromEl)\n            return false\n          }\n          if(fromEl.type === \"number\" && (fromEl.validity && fromEl.validity.badInput)){ return false }\n          if(!DOM.syncPendingRef(fromEl, toEl, disableWith)){\n            if(DOM.isUploadInput(fromEl)){\n              this.trackBefore(\"updated\", fromEl, toEl)\n              updates.push(fromEl)\n            }\n            DOM.applyStickyOperations(fromEl)\n            return false\n          }\n\n          // nested view handling\n          if(DOM.isPhxChild(toEl)){\n            let prevSession = fromEl.getAttribute(PHX_SESSION)\n            DOM.mergeAttrs(fromEl, toEl, {exclude: [PHX_STATIC]})\n            if(prevSession !== \"\"){ fromEl.setAttribute(PHX_SESSION, prevSession) }\n            fromEl.setAttribute(PHX_ROOT_ID, this.rootID)\n            DOM.applyStickyOperations(fromEl)\n            return false\n          }\n\n          // input handling\n          DOM.copyPrivates(toEl, fromEl)\n          DOM.discardError(targetContainer, toEl, phxFeedbackFor)\n\n          let isFocusedFormEl = focused && fromEl.isSameNode(focused) && DOM.isFormInput(fromEl)\n          if(isFocusedFormEl){\n            this.trackBefore(\"updated\", fromEl, toEl)\n            DOM.mergeFocusedInput(fromEl, toEl)\n            DOM.syncAttrsToProps(fromEl)\n            updates.push(fromEl)\n            DOM.applyStickyOperations(fromEl)\n            return false\n          } else {\n            if(DOM.isPhxUpdate(toEl, phxUpdate, [\"append\", \"prepend\"])){\n              appendPrependUpdates.push(new DOMPostMorphRestorer(fromEl, toEl, toEl.getAttribute(phxUpdate)))\n            }\n            DOM.syncAttrsToProps(toEl)\n            DOM.applyStickyOperations(toEl)\n            this.trackBefore(\"updated\", fromEl, toEl)\n            return true\n          }\n        }\n      })\n    })\n\n    if(liveSocket.isDebugEnabled()){ detectDuplicateIds() }\n\n    if(appendPrependUpdates.length > 0){\n      liveSocket.time(\"post-morph append/prepend restoration\", () => {\n        appendPrependUpdates.forEach(update => update.perform())\n      })\n    }\n\n    liveSocket.silenceEvents(() => DOM.restoreFocus(focused, selectionStart, selectionEnd))\n    DOM.dispatchEvent(document, \"phx:update\")\n    added.forEach(el => this.trackAfter(\"added\", el))\n    updates.forEach(el => this.trackAfter(\"updated\", el))\n\n    if(pendingRemoves.length > 0){\n      liveSocket.transitionRemoves(pendingRemoves)\n      liveSocket.requestDOMUpdate(() => {\n        pendingRemoves.forEach(el => {\n          let child = DOM.firstPhxChild(el)\n          if(child){ liveSocket.destroyViewByEl(child) }\n          el.remove()\n        })\n        this.trackAfter(\"transitionsDiscarded\", pendingRemoves)\n      })\n    }\n\n    if(externalFormTriggered){\n      liveSocket.disconnect()\n      externalFormTriggered.submit()\n    }\n    return true\n  }\n\n  isCIDPatch(){ return this.cidPatch }\n\n  skipCIDSibling(el){\n    return el.nodeType === Node.ELEMENT_NODE && el.getAttribute(PHX_SKIP) !== null\n  }\n\n  targetCIDContainer(html){\n    if(!this.isCIDPatch()){ return }\n    let [first, ...rest] = DOM.findComponentNodeList(this.container, this.targetCID)\n    if(rest.length === 0 && DOM.childNodeLength(html) === 1){\n      return first\n    } else {\n      return first && first.parentNode\n    }\n  }\n\n  // builds HTML for morphdom patch\n  // - for full patches of LiveView or a component with a single\n  //   root node, simply returns the HTML\n  // - for patches of a component with multiple root nodes, the\n  //   parent node becomes the target container and non-component\n  //   siblings are marked as skip.\n  buildDiffHTML(container, html, phxUpdate, targetContainer){\n    let isCIDPatch = this.isCIDPatch()\n    let isCIDWithSingleRoot = isCIDPatch && targetContainer.getAttribute(PHX_COMPONENT) === this.targetCID.toString()\n    if(!isCIDPatch || isCIDWithSingleRoot){\n      return html\n    } else {\n      // component patch with multiple CID roots\n      let diffContainer = null\n      let template = document.createElement(\"template\")\n      diffContainer = DOM.cloneNode(targetContainer)\n      let [firstComponent, ...rest] = DOM.findComponentNodeList(diffContainer, this.targetCID)\n      template.innerHTML = html\n      rest.forEach(el => el.remove())\n      Array.from(diffContainer.childNodes).forEach(child => {\n        // we can only skip trackable nodes with an ID\n        if(child.id && child.nodeType === Node.ELEMENT_NODE && child.getAttribute(PHX_COMPONENT) !== this.targetCID.toString()){\n          child.setAttribute(PHX_SKIP, \"\")\n          child.innerHTML = \"\"\n        }\n      })\n      Array.from(template.content.childNodes).forEach(el => diffContainer.insertBefore(el, firstComponent))\n      firstComponent.remove()\n      return diffContainer.outerHTML\n    }\n  }\n}\n", "import {\n  COMPONENTS,\n  DYNAMICS,\n  TEMPLATES,\n  EVENTS,\n  PHX_COMPONENT,\n  PHX_SKIP,\n  REPLY,\n  STATIC,\n  TITLE\n} from \"./constants\"\n\nimport {\n  isObject,\n  logError,\n  isCid,\n} from \"./utils\"\n\nexport default class Rendered {\n  static extract(diff){\n    let {[REPLY]: reply, [EVENTS]: events, [TITLE]: title} = diff\n    delete diff[REPLY]\n    delete diff[EVENTS]\n    delete diff[TITLE]\n    return {diff, title, reply: reply || null, events: events || []}\n  }\n\n  constructor(viewId, rendered){\n    this.viewId = viewId\n    this.rendered = {}\n    this.mergeDiff(rendered)\n  }\n\n  parentViewId(){ return this.viewId }\n\n  toString(onlyCids){\n    return this.recursiveToString(this.rendered, this.rendered[COMPONENTS], onlyCids)\n  }\n\n  recursiveToString(rendered, components = rendered[COMPONENTS], onlyCids){\n    onlyCids = onlyCids ? new Set(onlyCids) : null\n    let output = {buffer: \"\", components: components, onlyCids: onlyCids}\n    this.toOutputBuffer(rendered, null, output)\n    return output.buffer\n  }\n\n  componentCIDs(diff){ return Object.keys(diff[COMPONENTS] || {}).map(i => parseInt(i)) }\n\n  isComponentOnlyDiff(diff){\n    if(!diff[COMPONENTS]){ return false }\n    return Object.keys(diff).length === 1\n  }\n\n  getComponent(diff, cid){ return diff[COMPONENTS][cid] }\n\n  mergeDiff(diff){\n    let newc = diff[COMPONENTS]\n    let cache = {}\n    delete diff[COMPONENTS]\n    this.rendered = this.mutableMerge(this.rendered, diff)\n    this.rendered[COMPONENTS] = this.rendered[COMPONENTS] || {}\n\n    if(newc){\n      let oldc = this.rendered[COMPONENTS]\n\n      for(let cid in newc){\n        newc[cid] = this.cachedFindComponent(cid, newc[cid], oldc, newc, cache)\n      }\n\n      for(let cid in newc){ oldc[cid] = newc[cid] }\n      diff[COMPONENTS] = newc\n    }\n  }\n\n  cachedFindComponent(cid, cdiff, oldc, newc, cache){\n    if(cache[cid]){\n      return cache[cid]\n    } else {\n      let ndiff, stat, scid = cdiff[STATIC]\n\n      if(isCid(scid)){\n        let tdiff\n\n        if(scid > 0){\n          tdiff = this.cachedFindComponent(scid, newc[scid], oldc, newc, cache)\n        } else {\n          tdiff = oldc[-scid]\n        }\n\n        stat = tdiff[STATIC]\n        ndiff = this.cloneMerge(tdiff, cdiff)\n        ndiff[STATIC] = stat\n      } else {\n        ndiff = cdiff[STATIC] !== undefined ? cdiff : this.cloneMerge(oldc[cid] || {}, cdiff)\n      }\n\n      cache[cid] = ndiff\n      return ndiff\n    }\n  }\n\n  mutableMerge(target, source){\n    if(source[STATIC] !== undefined){\n      return source\n    } else {\n      this.doMutableMerge(target, source)\n      return target\n    }\n  }\n\n  doMutableMerge(target, source){\n    for(let key in source){\n      let val = source[key]\n      let targetVal = target[key]\n      if(isObject(val) && val[STATIC] === undefined && isObject(targetVal)){\n        this.doMutableMerge(targetVal, val)\n      } else {\n        target[key] = val\n      }\n    }\n  }\n\n  cloneMerge(target, source){\n    let merged = {...target, ...source}\n    for(let key in merged){\n      let val = source[key]\n      let targetVal = target[key]\n      if(isObject(val) && val[STATIC] === undefined && isObject(targetVal)){\n        merged[key] = this.cloneMerge(targetVal, val)\n      }\n    }\n    return merged\n  }\n\n  componentToString(cid){ return this.recursiveCIDToString(this.rendered[COMPONENTS], cid) }\n\n  pruneCIDs(cids){\n    cids.forEach(cid => delete this.rendered[COMPONENTS][cid])\n  }\n\n  // private\n\n  get(){ return this.rendered }\n\n  isNewFingerprint(diff = {}){ return !!diff[STATIC] }\n\n  templateStatic(part, templates){\n    if(typeof (part) === \"number\") {\n      return templates[part]\n    } else {\n      return part\n    }\n  }\n\n  toOutputBuffer(rendered, templates, output){\n    if(rendered[DYNAMICS]){ return this.comprehensionToBuffer(rendered, templates, output) }\n    let {[STATIC]: statics} = rendered\n    statics = this.templateStatic(statics, templates)\n\n    output.buffer += statics[0]\n    for(let i = 1; i < statics.length; i++){\n      this.dynamicToBuffer(rendered[i - 1], templates, output)\n      output.buffer += statics[i]\n    }\n  }\n\n  comprehensionToBuffer(rendered, templates, output){\n    let {[DYNAMICS]: dynamics, [STATIC]: statics} = rendered\n    statics = this.templateStatic(statics, templates)\n    let compTemplates = rendered[TEMPLATES]\n\n    for(let d = 0; d < dynamics.length; d++){\n      let dynamic = dynamics[d]\n      output.buffer += statics[0]\n      for(let i = 1; i < statics.length; i++){\n        this.dynamicToBuffer(dynamic[i - 1], compTemplates, output)\n        output.buffer += statics[i]\n      }\n    }\n  }\n\n  dynamicToBuffer(rendered, templates, output){\n    if(typeof (rendered) === \"number\"){\n      output.buffer += this.recursiveCIDToString(output.components, rendered, output.onlyCids)\n    } else if(isObject(rendered)){\n      this.toOutputBuffer(rendered, templates, output)\n    } else {\n      output.buffer += rendered\n    }\n  }\n\n  recursiveCIDToString(components, cid, onlyCids){\n    let component = components[cid] || logError(`no component for CID ${cid}`, components)\n    let template = document.createElement(\"template\")\n    template.innerHTML = this.recursiveToString(component, components, onlyCids)\n    let container = template.content\n    let skip = onlyCids && !onlyCids.has(cid)\n\n    let [hasChildNodes, hasChildComponents] =\n      Array.from(container.childNodes).reduce(([hasNodes, hasComponents], child, i) => {\n        if(child.nodeType === Node.ELEMENT_NODE){\n          if(child.getAttribute(PHX_COMPONENT)){\n            return [hasNodes, true]\n          }\n          child.setAttribute(PHX_COMPONENT, cid)\n          if(!child.id){ child.id = `${this.parentViewId()}-${cid}-${i}` }\n          if(skip){\n            child.setAttribute(PHX_SKIP, \"\")\n            child.innerHTML = \"\"\n          }\n          return [true, hasComponents]\n        } else {\n          if(child.nodeValue.trim() !== \"\"){\n            logError(\"only HTML element tags are allowed at the root of components.\\n\\n\" +\n              `got: \"${child.nodeValue.trim()}\"\\n\\n` +\n              \"within:\\n\", template.innerHTML.trim())\n            child.replaceWith(this.createSpan(child.nodeValue, cid))\n            return [true, hasComponents]\n          } else {\n            child.remove()\n            return [hasNodes, hasComponents]\n          }\n        }\n      }, [false, false])\n\n    if(!hasChildNodes && !hasChildComponents){\n      logError(\"expected at least one HTML element tag inside a component, but the component is empty:\\n\",\n        template.innerHTML.trim())\n      return this.createSpan(\"\", cid).outerHTML\n    } else if(!hasChildNodes && hasChildComponents){\n      logError(\"expected at least one HTML element tag directly inside a component, but only subcomponents were found. A component must render at least one HTML tag directly inside itself.\",\n        template.innerHTML.trim())\n      return template.innerHTML\n    } else {\n      return template.innerHTML\n    }\n  }\n\n  createSpan(text, cid){\n    let span = document.createElement(\"span\")\n    span.innerText = text\n    span.setAttribute(PHX_COMPONENT, cid)\n    return span\n  }\n}\n", "let viewHookID = 1\nexport default class ViewHook {\n  static makeID(){ return viewHookID++ }\n  static elementID(el){ return el.phxHookId }\n\n  constructor(view, el, callbacks){\n    this.__view = view\n    this.__liveSocket = view.liveSocket\n    this.__callbacks = callbacks\n    this.__listeners = new Set()\n    this.__isDisconnected = false\n    this.el = el\n    this.el.phxHookId = this.constructor.makeID()\n    for(let key in this.__callbacks){ this[key] = this.__callbacks[key] }\n  }\n\n  __mounted(){ this.mounted && this.mounted() }\n  __updated(){ this.updated && this.updated() }\n  __beforeUpdate(){ this.beforeUpdate && this.beforeUpdate() }\n  __destroyed(){ this.destroyed && this.destroyed() }\n  __reconnected(){\n    if(this.__isDisconnected){\n      this.__isDisconnected = false\n      this.reconnected && this.reconnected()\n    }\n  }\n  __disconnected(){\n    this.__isDisconnected = true\n    this.disconnected && this.disconnected()\n  }\n\n  pushEvent(event, payload = {}, onReply = function (){ }){\n    return this.__view.pushHookEvent(null, event, payload, onReply)\n  }\n\n  pushEventTo(phxTarget, event, payload = {}, onReply = function (){ }){\n    return this.__view.withinTargets(phxTarget, (view, targetCtx) => {\n      return view.pushHookEvent(targetCtx, event, payload, onReply)\n    })\n  }\n\n  handleEvent(event, callback){\n    let callbackRef = (customEvent, bypass) => bypass ? event : callback(customEvent.detail)\n    window.addEventListener(`phx:${event}`, callbackRef)\n    this.__listeners.add(callbackRef)\n    return callbackRef\n  }\n\n  removeHandleEvent(callbackRef){\n    let event = callbackRef(null, true)\n    window.removeEventListener(`phx:${event}`, callbackRef)\n    this.__listeners.delete(callbackRef)\n  }\n\n  upload(name, files){\n    return this.__view.dispatchUploads(name, files)\n  }\n\n  uploadTo(phxTarget, name, files){\n    return this.__view.withinTargets(phxTarget, view => view.dispatchUploads(name, files))\n  }\n\n  __cleanup__(){\n    this.__listeners.forEach(callbackRef => this.removeHandleEvent(callbackRef))\n  }\n}\n", "import DOM from \"./dom\"\n\nlet JS = {\n  exec(eventType, phxEvent, view, el, defaults){\n    let [defaultKind, defaultArgs] = defaults || [null, {}]\n    let commands = phxEvent.charAt(0) === \"[\" ?\n      JSON.parse(phxEvent) : [[defaultKind, defaultArgs]]\n\n    commands.forEach(([kind, args]) => {\n      if(kind === defaultKind && defaultArgs.data){\n        args.data = Object.assign(args.data || {}, defaultArgs.data)\n      }\n      this[`exec_${kind}`](eventType, phxEvent, view, el, args)\n    })\n  },\n\n  isVisible(el){\n    let style = window.getComputedStyle(el)\n    return !(style.opacity === 0 || style.display === \"none\")\n  },\n\n  // private\n\n  // commands\n\n  exec_dispatch(eventType, phxEvent, view, sourceEl, {to, event, detail}){\n    if(to){\n      DOM.all(document, to, el => DOM.dispatchEvent(el, event, detail))\n    } else {\n      DOM.dispatchEvent(sourceEl, event, detail)\n    }\n  },\n\n  exec_push(eventType, phxEvent, view, sourceEl, args){\n    let {event, data, target, page_loading, loading, value} = args\n    let pushOpts = {page_loading: !!page_loading, loading: loading, value: value}\n    let targetSrc = eventType === \"change\" ? sourceEl.form : sourceEl\n    let phxTarget = target || targetSrc.getAttribute(view.binding(\"target\")) || targetSrc\n    view.withinTargets(phxTarget, (targetView, targetCtx) => {\n      if(eventType === \"change\"){\n        let {newCid, _target, callback} = args\n        if(_target){ pushOpts._target = _target }\n        targetView.pushInput(sourceEl, targetCtx, newCid, event || phxEvent, pushOpts, callback)\n      } else if(eventType === \"submit\"){\n        targetView.submitForm(sourceEl, targetCtx, event || phxEvent, pushOpts)\n      } else {\n        targetView.pushEvent(eventType, sourceEl, targetCtx, event || phxEvent, data, pushOpts)\n      }\n    })\n  },\n\n  exec_add_class(eventType, phxEvent, view, sourceEl, {to, names, transition, time}){\n    if(to){\n      DOM.all(document, to, el => this.addOrRemoveClasses(el, names, [], transition, time, view))\n    } else {\n      this.addOrRemoveClasses(sourceEl, names, [], transition, view)\n    }\n  },\n\n  exec_remove_class(eventType, phxEvent, view, sourceEl, {to, names, transition, time}){\n    if(to){\n      DOM.all(document, to, el => this.addOrRemoveClasses(el, [], names, transition, time, view))\n    } else {\n      this.addOrRemoveClasses(sourceEl, [], names, transition, time, view)\n    }\n  },\n\n  exec_transition(eventType, phxEvent, view, sourceEl, {time, to, transition}){\n    let els = to ? DOM.all(document, to) : [sourceEl]\n    let [transition_start, running, transition_end] = transition\n    els.forEach(el => {\n      let onStart = () => this.addOrRemoveClasses(el, transition_start.concat(running), [])\n      let onDone = () => this.addOrRemoveClasses(el, transition_end, transition_start.concat(running))\n      view.transition(time, onStart, onDone)\n    })\n  },\n\n  exec_toggle(eventType, phxEvent, view, sourceEl, {to, display, ins, outs, time}){\n    if(to){\n      DOM.all(document, to, el => this.toggle(eventType, view, el, display, ins, outs, time))\n    } else {\n      this.toggle(eventType, view, sourceEl, display, ins, outs, time)\n    }\n  },\n\n  exec_show(eventType, phxEvent, view, sourceEl, {to, display, transition, time}){\n    if(to){\n      DOM.all(document, to, el => this.show(eventType, view, el, display, transition, time))\n    } else {\n      this.show(eventType, view, sourceEl, transition, time)\n    }\n  },\n\n  exec_hide(eventType, phxEvent, view, sourceEl, {to, display, transition, time}){\n    if(to){\n      DOM.all(document, to, el => this.hide(eventType, view, el, display, transition, time))\n    } else {\n      this.hide(eventType, view, sourceEl, display, transition, time)\n    }\n  },\n\n  // utils for commands\n\n  show(eventType, view, el, display, transition, time){\n    if(!this.isVisible(el)){\n      this.toggle(eventType, view, el, display, transition, null, time)\n    }\n  },\n\n  hide(eventType, view, el, display, transition, time){\n    if(this.isVisible(el)){\n      this.toggle(eventType, view, el, display, null, transition, time)\n    }\n  },\n\n  toggle(eventType, view, el, display, ins, outs, time){\n    let [inClasses, inStartClasses, inEndClasses] = ins || [[], [], []]\n    let [outClasses, outStartClasses, outEndClasses] = outs || [[], [], []]\n    if(inClasses.length > 0 || outClasses.length > 0){\n      if(this.isVisible(el)){\n        let onStart = () => {\n          this.addOrRemoveClasses(el, outStartClasses, inClasses.concat(inStartClasses).concat(inEndClasses))\n          window.requestAnimationFrame(() => {\n            this.addOrRemoveClasses(el, outClasses, [])\n            window.requestAnimationFrame(() => this.addOrRemoveClasses(el, outEndClasses, outStartClasses))\n          })\n        }\n        view.transition(time, onStart, () => {\n          this.addOrRemoveClasses(el, [], outClasses.concat(outEndClasses))\n          DOM.putSticky(el, \"toggle\", currentEl => currentEl.style.display = \"none\")\n        })\n      } else {\n        if(eventType === \"remove\"){ return }\n        let onStart = () => {\n          this.addOrRemoveClasses(el, inStartClasses, outClasses.concat(outStartClasses).concat(outEndClasses))\n          DOM.putSticky(el, \"toggle\", currentEl => currentEl.style.display = (display || \"block\"))\n          window.requestAnimationFrame(() => {\n            this.addOrRemoveClasses(el, inClasses, [])\n            window.requestAnimationFrame(() => this.addOrRemoveClasses(el, inEndClasses, inStartClasses))\n          })\n        }\n        view.transition(time, onStart, () => {\n          this.addOrRemoveClasses(el, [], inClasses.concat(inEndClasses))\n        })\n      }\n    } else {\n      let newDisplay = this.isVisible(el) ? \"none\" : (display || \"block\")\n      DOM.putSticky(el, \"toggle\", currentEl => currentEl.style.display = newDisplay)\n    }\n  },\n\n  addOrRemoveClasses(el, adds, removes, transition, time, view){\n    let [transition_run, transition_start, transition_end] = transition || [[], [], []]\n    if(transition_run.length > 0){\n      let onStart = () => this.addOrRemoveClasses(el, transition_start.concat(transition_run), [])\n      let onDone = () => this.addOrRemoveClasses(el, adds.concat(transition_end), removes.concat(transition_run).concat(transition_start))\n      return view.transition(time, onStart, onDone)\n    }\n    window.requestAnimationFrame(() => {\n      let [prevAdds, prevRemoves] = DOM.getSticky(el, \"classes\", [[], []])\n      let keepAdds = adds.filter(name => prevAdds.indexOf(name) < 0 && !el.classList.contains(name))\n      let keepRemoves = removes.filter(name => prevRemoves.indexOf(name) < 0 && el.classList.contains(name))\n      let newAdds = prevAdds.filter(name => removes.indexOf(name) < 0).concat(keepAdds)\n      let newRemoves = prevRemoves.filter(name => adds.indexOf(name) < 0).concat(keepRemoves)\n\n      DOM.putSticky(el, \"classes\", currentEl => {\n        currentEl.classList.remove(...newRemoves)\n        currentEl.classList.add(...newAdds)\n        return [newAdds, newRemoves]\n      })\n    })\n  },\n\n  hasAllClasses(el, classes){ return classes.every(name => el.classList.contains(name)) },\n\n  isToggledOut(el, outClasses){\n    return !this.isVisible(el) || this.hasAllClasses(el, outClasses)\n  }\n}\n\nexport default JS\n", "import {\n  BEFORE_UNLOAD_LOADER_TIMEOUT,\n  CHECKABLE_INPUTS,\n  CONSECUTIVE_RELOADS,\n  PHX_AUTO_RECOVER,\n  PHX_COMPONENT,\n  PHX_CONNECTED_CLASS,\n  PHX_DISABLE_WITH,\n  PHX_DISABLE_WITH_RESTORE,\n  PHX_DISABLED,\n  PHX_DISCONNECTED_CLASS,\n  PHX_EVENT_CLASSES,\n  PHX_ERROR_CLASS,\n  PHX_FEEDBACK_FOR,\n  PHX_HAS_SUBMITTED,\n  PHX_HOOK,\n  PHX_PAGE_LOADING,\n  PHX_PARENT_ID,\n  PHX_PROGRESS,\n  PHX_READONLY,\n  PHX_REF,\n  PHX_ROOT_ID,\n  PHX_SESSION,\n  PHX_STATIC,\n  PHX_TRACK_STATIC,\n  PHX_TRACK_UPLOADS,\n  PHX_UPDATE,\n  PHX_UPLOAD_REF,\n  PHX_VIEW_SELECTOR,\n  PUSH_TIMEOUT,\n} from \"./constants\"\n\nimport {\n  clone,\n  closestPhxBinding,\n  isEmpty,\n  isEqualObj,\n  logError,\n  maybe,\n  isCid,\n} from \"./utils\"\n\nimport Browser from \"./browser\"\nimport DOM from \"./dom\"\nimport DOMPatch from \"./dom_patch\"\nimport LiveUploader from \"./live_uploader\"\nimport Rendered from \"./rendered\"\nimport ViewHook from \"./view_hook\"\nimport JS from \"./js\"\n\nlet serializeForm = (form, meta = {}) => {\n  let formData = new FormData(form)\n  let toRemove = []\n\n  formData.forEach((val, key, _index) => {\n    if(val instanceof File){ toRemove.push(key) }\n  })\n\n  // Cleanup after building fileData\n  toRemove.forEach(key => formData.delete(key))\n\n  let params = new URLSearchParams()\n  for(let [key, val] of formData.entries()){ params.append(key, val) }\n  for(let metaKey in meta){ params.append(metaKey, meta[metaKey]) }\n\n  return params.toString()\n}\n\nexport default class View {\n  constructor(el, liveSocket, parentView, flash){\n    this.liveSocket = liveSocket\n    this.flash = flash\n    this.parent = parentView\n    this.root = parentView ? parentView.root : this\n    this.el = el\n    this.id = this.el.id\n    this.ref = 0\n    this.childJoins = 0\n    this.loaderTimer = null\n    this.pendingDiffs = []\n    this.pruningCIDs = []\n    this.redirect = false\n    this.href = null\n    this.joinCount = this.parent ? this.parent.joinCount - 1 : 0\n    this.joinPending = true\n    this.destroyed = false\n    this.joinCallback = function(onDone){ onDone && onDone() }\n    this.stopCallback = function(){ }\n    this.pendingJoinOps = this.parent ? null : []\n    this.viewHooks = {}\n    this.uploaders = {}\n    this.formSubmits = []\n    this.children = this.parent ? null : {}\n    this.root.children[this.id] = {}\n    this.channel = this.liveSocket.channel(`lv:${this.id}`, () => {\n      return {\n        redirect: this.redirect ? this.href : undefined,\n        url: this.redirect ? undefined : this.href || undefined,\n        params: this.connectParams(),\n        session: this.getSession(),\n        static: this.getStatic(),\n        flash: this.flash\n      }\n    })\n    this.showLoader(this.liveSocket.loaderTimeout)\n    this.bindChannel()\n  }\n\n  setHref(href){ this.href = href }\n\n  setRedirect(href){\n    this.redirect = true\n    this.href = href\n  }\n\n  isMain(){ return this.liveSocket.main === this }\n\n  connectParams(){\n    let params = this.liveSocket.params(this.el)\n    let manifest =\n      DOM.all(document, `[${this.binding(PHX_TRACK_STATIC)}]`)\n        .map(node => node.src || node.href).filter(url => typeof (url) === \"string\")\n\n    if(manifest.length > 0){ params[\"_track_static\"] = manifest }\n    params[\"_mounts\"] = this.joinCount\n\n    return params\n  }\n\n  isConnected(){ return this.channel.canPush() }\n\n  getSession(){ return this.el.getAttribute(PHX_SESSION) }\n\n  getStatic(){\n    let val = this.el.getAttribute(PHX_STATIC)\n    return val === \"\" ? null : val\n  }\n\n  destroy(callback = function (){ }){\n    this.destroyAllChildren()\n    this.destroyed = true\n    delete this.root.children[this.id]\n    if(this.parent){ delete this.root.children[this.parent.id][this.id] }\n    clearTimeout(this.loaderTimer)\n    let onFinished = () => {\n      callback()\n      for(let id in this.viewHooks){\n        this.destroyHook(this.viewHooks[id])\n      }\n    }\n\n    DOM.markPhxChildDestroyed(this.el)\n\n    this.log(\"destroyed\", () => [\"the child has been removed from the parent\"])\n    this.channel.leave()\n      .receive(\"ok\", onFinished)\n      .receive(\"error\", onFinished)\n      .receive(\"timeout\", onFinished)\n  }\n\n  setContainerClasses(...classes){\n    this.el.classList.remove(\n      PHX_CONNECTED_CLASS,\n      PHX_DISCONNECTED_CLASS,\n      PHX_ERROR_CLASS\n    )\n    this.el.classList.add(...classes)\n  }\n\n  showLoader(timeout){\n    clearTimeout(this.loaderTimer)\n    if(timeout){\n      this.loaderTimer = setTimeout(() => this.showLoader(), timeout)\n    } else {\n      for(let id in this.viewHooks){ this.viewHooks[id].__disconnected() }\n      this.setContainerClasses(PHX_DISCONNECTED_CLASS)\n    }\n  }\n\n  hideLoader(){\n    clearTimeout(this.loaderTimer)\n    this.setContainerClasses(PHX_CONNECTED_CLASS)\n  }\n\n  triggerReconnected(){\n    for(let id in this.viewHooks){ this.viewHooks[id].__reconnected() }\n  }\n\n  log(kind, msgCallback){\n    this.liveSocket.log(this, kind, msgCallback)\n  }\n\n  transition(time, onStart, onDone = function(){}){\n    this.liveSocket.transition(time, onStart, onDone)\n  }\n\n  withinTargets(phxTarget, callback){\n    if(phxTarget instanceof HTMLElement || phxTarget instanceof SVGElement){\n      return this.liveSocket.owner(phxTarget, view => callback(view, phxTarget))\n    }\n\n    if(isCid(phxTarget)){\n      let targets = DOM.findComponentNodeList(this.el, phxTarget)\n      if(targets.length === 0){\n        logError(`no component found matching phx-target of ${phxTarget}`)\n      } else {\n        callback(this, parseInt(phxTarget))\n      }\n    } else {\n      let targets = Array.from(document.querySelectorAll(phxTarget))\n      if(targets.length === 0){ logError(`nothing found matching the phx-target selector \"${phxTarget}\"`) }\n      targets.forEach(target => this.liveSocket.owner(target, view => callback(view, target)))\n    }\n  }\n\n  applyDiff(type, rawDiff, callback){\n    this.log(type, () => [\"\", clone(rawDiff)])\n    let {diff, reply, events, title} = Rendered.extract(rawDiff)\n    if(title){ DOM.putTitle(title) }\n\n    callback({diff, reply, events})\n    return reply\n  }\n\n  onJoin(resp){\n    let {rendered, container} = resp\n    if(container){\n      let [tag, attrs] = container\n      this.el = DOM.replaceRootContainer(this.el, tag, attrs)\n    }\n    this.childJoins = 0\n    this.joinPending = true\n    this.flash = null\n\n    Browser.dropLocal(this.liveSocket.localStorage, window.location.pathname, CONSECUTIVE_RELOADS)\n    this.applyDiff(\"mount\", rendered, ({diff, events}) => {\n      this.rendered = new Rendered(this.id, diff)\n      let html = this.renderContainer(null, \"join\")\n      this.dropPendingRefs()\n      let forms = this.formsForRecovery(html)\n      this.joinCount++\n\n      if(forms.length > 0){\n        forms.forEach(([form, newForm, newCid], i) => {\n          this.pushFormRecovery(form, newCid, resp => {\n            if(i === forms.length - 1){\n              this.onJoinComplete(resp, html, events)\n            }\n          })\n        })\n      } else {\n        this.onJoinComplete(resp, html, events)\n      }\n    })\n  }\n\n  dropPendingRefs(){ DOM.all(this.el, `[${PHX_REF}]`, el => el.removeAttribute(PHX_REF)) }\n\n  onJoinComplete({live_patch}, html, events){\n    // In order to provide a better experience, we want to join\n    // all LiveViews first and only then apply their patches.\n    if(this.joinCount > 1 || (this.parent && !this.parent.isJoinPending())){\n      return this.applyJoinPatch(live_patch, html, events)\n    }\n\n    // One downside of this approach is that we need to find phxChildren\n    // in the html fragment, instead of directly on the DOM. The fragment\n    // also does not include PHX_STATIC, so we need to copy it over from\n    // the DOM.\n    let newChildren = DOM.findPhxChildrenInFragment(html, this.id).filter(toEl => {\n      let fromEl = toEl.id && this.el.querySelector(`[id=\"${toEl.id}\"]`)\n      let phxStatic = fromEl && fromEl.getAttribute(PHX_STATIC)\n      if(phxStatic){ toEl.setAttribute(PHX_STATIC, phxStatic) }\n      return this.joinChild(toEl)\n    })\n\n    if(newChildren.length === 0){\n      if(this.parent){\n        this.root.pendingJoinOps.push([this, () => this.applyJoinPatch(live_patch, html, events)])\n        this.parent.ackJoin(this)\n      } else {\n        this.onAllChildJoinsComplete()\n        this.applyJoinPatch(live_patch, html, events)\n      }\n    } else {\n      this.root.pendingJoinOps.push([this, () => this.applyJoinPatch(live_patch, html, events)])\n    }\n  }\n\n  attachTrueDocEl(){\n    this.el = DOM.byId(this.id)\n    this.el.setAttribute(PHX_ROOT_ID, this.root.id)\n  }\n\n  applyJoinPatch(live_patch, html, events){\n    this.attachTrueDocEl()\n    let patch = new DOMPatch(this, this.el, this.id, html, null)\n    patch.markPrunableContentForRemoval()\n    this.performPatch(patch, false)\n    this.joinNewChildren()\n    DOM.all(this.el, `[${this.binding(PHX_HOOK)}], [data-phx-${PHX_HOOK}]`, hookEl => {\n      let hook = this.addHook(hookEl)\n      if(hook){ hook.__mounted() }\n    })\n\n    this.joinPending = false\n    this.liveSocket.dispatchEvents(events)\n    this.applyPendingUpdates()\n\n    if(live_patch){\n      let {kind, to} = live_patch\n      this.liveSocket.historyPatch(to, kind)\n    }\n    this.hideLoader()\n    if(this.joinCount > 1){ this.triggerReconnected() }\n    this.stopCallback()\n  }\n\n  triggerBeforeUpdateHook(fromEl, toEl){\n    this.liveSocket.triggerDOM(\"onBeforeElUpdated\", [fromEl, toEl])\n    let hook = this.getHook(fromEl)\n    let isIgnored = hook && DOM.isIgnored(fromEl, this.binding(PHX_UPDATE))\n    if(hook && !fromEl.isEqualNode(toEl) && !(isIgnored && isEqualObj(fromEl.dataset, toEl.dataset))){\n      hook.__beforeUpdate()\n      return hook\n    }\n  }\n\n  performPatch(patch, pruneCids){\n    let removedEls = []\n    let phxChildrenAdded = false\n    let updatedHookIds = new Set()\n\n    patch.after(\"added\", el => {\n      this.liveSocket.triggerDOM(\"onNodeAdded\", [el])\n\n      let newHook = this.addHook(el)\n      if(newHook){ newHook.__mounted() }\n    })\n\n    patch.after(\"phxChildAdded\", _el => phxChildrenAdded = true)\n\n    patch.before(\"updated\", (fromEl, toEl) => {\n      let hook = this.triggerBeforeUpdateHook(fromEl, toEl)\n      if(hook){ updatedHookIds.add(fromEl.id) }\n    })\n\n    patch.after(\"updated\", el => {\n      if(updatedHookIds.has(el.id)){ this.getHook(el).__updated() }\n    })\n\n    patch.after(\"discarded\", (el) => {\n      if(el.nodeType === Node.ELEMENT_NODE){ removedEls.push(el) }\n    })\n\n    patch.after(\"transitionsDiscarded\", els => this.afterElementsRemoved(els, pruneCids))\n    patch.perform()\n    this.afterElementsRemoved(removedEls, pruneCids)\n\n    return phxChildrenAdded\n  }\n\n  afterElementsRemoved(elements, pruneCids){\n    let destroyedCIDs = []\n    elements.forEach(parent => {\n      let components = DOM.all(parent, `[${PHX_COMPONENT}]`)\n        components.concat(parent).forEach(el => {\n        let cid = this.componentID(el)\n        if(isCid(cid) && destroyedCIDs.indexOf(cid) === -1){ destroyedCIDs.push(cid) }\n        let hook = this.getHook(el)\n        hook && this.destroyHook(hook)\n      })\n    })\n    // We should not pruneCids on joins. Otherwise, in case of\n    // rejoins, we may notify cids that no longer belong to the\n    // current LiveView to be removed.\n    if(pruneCids){\n      this.maybePushComponentsDestroyed(destroyedCIDs)\n    }\n  }\n\n  joinNewChildren(){\n    DOM.findPhxChildren(this.el, this.id).forEach(el => this.joinChild(el))\n  }\n\n  getChildById(id){ return this.root.children[this.id][id] }\n\n  getDescendentByEl(el){\n    if(el.id === this.id){\n      return this\n    } else {\n      return this.children[el.getAttribute(PHX_PARENT_ID)][el.id]\n    }\n  }\n\n  destroyDescendent(id){\n    for(let parentId in this.root.children){\n      for(let childId in this.root.children[parentId]){\n        if(childId === id){ return this.root.children[parentId][childId].destroy() }\n      }\n    }\n  }\n\n  joinChild(el){\n    let child = this.getChildById(el.id)\n    if(!child){\n      let view = new View(el, this.liveSocket, this)\n      this.root.children[this.id][view.id] = view\n      view.join()\n      this.childJoins++\n      return true\n    }\n  }\n\n  isJoinPending(){ return this.joinPending }\n\n  ackJoin(_child){\n    this.childJoins--\n\n    if(this.childJoins === 0){\n      if(this.parent){\n        this.parent.ackJoin(this)\n      } else {\n        this.onAllChildJoinsComplete()\n      }\n    }\n  }\n\n  onAllChildJoinsComplete(){\n    this.joinCallback(() => {\n      this.pendingJoinOps.forEach(([view, op]) => {\n        if(!view.isDestroyed()){ op() }\n      })\n      this.pendingJoinOps = []\n    })\n  }\n\n  update(diff, events){\n    if(this.isJoinPending() || this.liveSocket.hasPendingLink()){\n      return this.pendingDiffs.push({diff, events})\n    }\n\n    this.rendered.mergeDiff(diff)\n    let phxChildrenAdded = false\n\n    // When the diff only contains component diffs, then walk components\n    // and patch only the parent component containers found in the diff.\n    // Otherwise, patch entire LV container.\n    if(this.rendered.isComponentOnlyDiff(diff)){\n      this.liveSocket.time(\"component patch complete\", () => {\n        let parentCids = DOM.findParentCIDs(this.el, this.rendered.componentCIDs(diff))\n        parentCids.forEach(parentCID => {\n          if(this.componentPatch(this.rendered.getComponent(diff, parentCID), parentCID)){ phxChildrenAdded = true }\n        })\n      })\n    } else if(!isEmpty(diff)){\n      this.liveSocket.time(\"full patch complete\", () => {\n        let html = this.renderContainer(diff, \"update\")\n        let patch = new DOMPatch(this, this.el, this.id, html, null)\n        phxChildrenAdded = this.performPatch(patch, true)\n      })\n    }\n\n    this.liveSocket.dispatchEvents(events)\n    if(phxChildrenAdded){ this.joinNewChildren() }\n  }\n\n  renderContainer(diff, kind){\n    return this.liveSocket.time(`toString diff (${kind})`, () => {\n      let tag = this.el.tagName\n      // Don't skip any component in the diff nor any marked as pruned\n      // (as they may have been added back)\n      let cids = diff ? this.rendered.componentCIDs(diff).concat(this.pruningCIDs) : null\n      let html = this.rendered.toString(cids)\n      return `<${tag}>${html}</${tag}>`\n    })\n  }\n\n  componentPatch(diff, cid){\n    if(isEmpty(diff)) return false\n    let html = this.rendered.componentToString(cid)\n    let patch = new DOMPatch(this, this.el, this.id, html, cid)\n    let childrenAdded = this.performPatch(patch, true)\n    return childrenAdded\n  }\n\n  getHook(el){ return this.viewHooks[ViewHook.elementID(el)] }\n\n  addHook(el){\n    if(ViewHook.elementID(el) || !el.getAttribute){ return }\n    let hookName = el.getAttribute(`data-phx-${PHX_HOOK}`) || el.getAttribute(this.binding(PHX_HOOK))\n    if(hookName && !this.ownsElement(el)){ return }\n    let callbacks = this.liveSocket.getHookCallbacks(hookName)\n\n    if(callbacks){\n      if(!el.id){ logError(`no DOM ID for hook \"${hookName}\". Hooks require a unique ID on each element.`, el) }\n      let hook = new ViewHook(this, el, callbacks)\n      this.viewHooks[ViewHook.elementID(hook.el)] = hook\n      return hook\n    } else if(hookName !== null){\n      logError(`unknown hook found for \"${hookName}\"`, el)\n    }\n  }\n\n  destroyHook(hook){\n    hook.__destroyed()\n    hook.__cleanup__()\n    delete this.viewHooks[ViewHook.elementID(hook.el)]\n  }\n\n  applyPendingUpdates(){\n    this.pendingDiffs.forEach(({diff, events}) => this.update(diff, events))\n    this.pendingDiffs = []\n  }\n\n  onChannel(event, cb){\n    this.liveSocket.onChannel(this.channel, event, resp => {\n      if(this.isJoinPending()){\n        this.root.pendingJoinOps.push([this, () => cb(resp)])\n      } else {\n        this.liveSocket.requestDOMUpdate(() => cb(resp))\n      }\n    })\n  }\n\n  bindChannel(){\n    // The diff event should be handled by the regular update operations.\n    // All other operations are queued to be applied only after join.\n    this.liveSocket.onChannel(this.channel, \"diff\", (rawDiff) => {\n      this.liveSocket.requestDOMUpdate(() => {\n        this.applyDiff(\"update\", rawDiff, ({diff, events}) => this.update(diff, events))\n      })\n    })\n    this.onChannel(\"redirect\", ({to, flash}) => this.onRedirect({to, flash}))\n    this.onChannel(\"live_patch\", (redir) => this.onLivePatch(redir))\n    this.onChannel(\"live_redirect\", (redir) => this.onLiveRedirect(redir))\n    this.channel.onError(reason => this.onError(reason))\n    this.channel.onClose(reason => this.onClose(reason))\n  }\n\n  destroyAllChildren(){\n    for(let id in this.root.children[this.id]){\n      this.getChildById(id).destroy()\n    }\n  }\n\n  onLiveRedirect(redir){\n    let {to, kind, flash} = redir\n    let url = this.expandURL(to)\n    this.liveSocket.historyRedirect(url, kind, flash)\n  }\n\n  onLivePatch(redir){\n    let {to, kind} = redir\n    this.href = this.expandURL(to)\n    this.liveSocket.historyPatch(to, kind)\n  }\n\n  expandURL(to){\n    return to.startsWith(\"/\") ? `${window.location.protocol}//${window.location.host}${to}` : to\n  }\n\n  onRedirect({to, flash}){ this.liveSocket.redirect(to, flash) }\n\n  isDestroyed(){ return this.destroyed }\n\n  join(callback){\n    if(!this.parent){\n      this.stopCallback = this.liveSocket.withPageLoading({to: this.href, kind: \"initial\"})\n    }\n    this.joinCallback = (onDone) => {\n      onDone = onDone || function(){}\n      callback ? callback(this.joinCount, onDone) : onDone()\n    }\n    this.liveSocket.wrapPush(this, {timeout: false}, () => {\n      return this.channel.join()\n        .receive(\"ok\", data => {\n          if(!this.isDestroyed()){\n            this.liveSocket.requestDOMUpdate(() => this.onJoin(data))\n          }\n        })\n        .receive(\"error\", resp => !this.isDestroyed() && this.onJoinError(resp))\n        .receive(\"timeout\", () => !this.isDestroyed() && this.onJoinError({reason: \"timeout\"}))\n    })\n  }\n\n  onJoinError(resp){\n    if(resp.reason === \"unauthorized\" || resp.reason === \"stale\"){\n      this.log(\"error\", () => [\"unauthorized live_redirect. Falling back to page request\", resp])\n      return this.onRedirect({to: this.href})\n    }\n    if(resp.redirect || resp.live_redirect){\n      this.joinPending = false\n      this.channel.leave()\n    }\n    if(resp.redirect){ return this.onRedirect(resp.redirect) }\n    if(resp.live_redirect){ return this.onLiveRedirect(resp.live_redirect) }\n    this.log(\"error\", () => [\"unable to join\", resp])\n    return this.liveSocket.reloadWithJitter(this)\n  }\n\n  onClose(reason){\n    if(this.isDestroyed()){ return }\n    if((this.isJoinPending() && document.visibilityState !== \"hidden\") ||\n      (this.liveSocket.hasPendingLink() && reason !== \"leave\")){\n\n      return this.liveSocket.reloadWithJitter(this)\n    }\n    this.destroyAllChildren()\n    this.liveSocket.dropActiveElement(this)\n    // document.activeElement can be null in Internet Explorer 11\n    if(document.activeElement){ document.activeElement.blur() }\n    if(this.liveSocket.isUnloaded()){\n      this.showLoader(BEFORE_UNLOAD_LOADER_TIMEOUT)\n    }\n  }\n\n  onError(reason){\n    this.onClose(reason)\n    this.log(\"error\", () => [\"view crashed\", reason])\n    if(!this.liveSocket.isUnloaded()){ this.displayError() }\n  }\n\n  displayError(){\n    if(this.isMain()){ DOM.dispatchEvent(window, \"phx:page-loading-start\", {to: this.href, kind: \"error\"}) }\n    this.showLoader()\n    this.setContainerClasses(PHX_DISCONNECTED_CLASS, PHX_ERROR_CLASS)\n  }\n\n  pushWithReply(refGenerator, event, payload, onReply = function (){ }){\n    if(!this.isConnected()){ return }\n\n    let [ref, [el], opts] = refGenerator ? refGenerator() : [null, [], {}]\n    let onLoadingDone = function(){ }\n    if(opts.page_loading || (el && (el.getAttribute(this.binding(PHX_PAGE_LOADING)) !== null))){\n      onLoadingDone = this.liveSocket.withPageLoading({kind: \"element\", target: el})\n    }\n\n    if(typeof (payload.cid) !== \"number\"){ delete payload.cid }\n    return (\n      this.liveSocket.wrapPush(this, {timeout: true}, () => {\n        return this.channel.push(event, payload, PUSH_TIMEOUT).receive(\"ok\", resp => {\n          this.liveSocket.requestDOMUpdate(() => {\n            let hookReply = null\n            if(ref !== null){ this.undoRefs(ref) }\n            if(resp.diff){\n              hookReply = this.applyDiff(\"update\", resp.diff, ({diff, events}) => {\n                this.update(diff, events)\n              })\n            }\n            if(resp.redirect){ this.onRedirect(resp.redirect) }\n            if(resp.live_patch){ this.onLivePatch(resp.live_patch) }\n            if(resp.live_redirect){ this.onLiveRedirect(resp.live_redirect) }\n            onLoadingDone()\n            onReply(resp, hookReply)\n          })\n        })\n      })\n    )\n  }\n\n  undoRefs(ref){\n    DOM.all(this.el, `[${PHX_REF}=\"${ref}\"]`, el => {\n      let disabledVal = el.getAttribute(PHX_DISABLED)\n      // remove refs\n      el.removeAttribute(PHX_REF)\n      // restore inputs\n      if(el.getAttribute(PHX_READONLY) !== null){\n        el.readOnly = false\n        el.removeAttribute(PHX_READONLY)\n      }\n      if(disabledVal !== null){\n        el.disabled = disabledVal === \"true\" ? true : false\n        el.removeAttribute(PHX_DISABLED)\n      }\n      // remove classes\n      PHX_EVENT_CLASSES.forEach(className => DOM.removeClass(el, className))\n      // restore disables\n      let disableRestore = el.getAttribute(PHX_DISABLE_WITH_RESTORE)\n      if(disableRestore !== null){\n        el.innerText = disableRestore\n        el.removeAttribute(PHX_DISABLE_WITH_RESTORE)\n      }\n      let toEl = DOM.private(el, PHX_REF)\n      if(toEl){\n        let hook = this.triggerBeforeUpdateHook(el, toEl)\n        DOMPatch.patchEl(el, toEl, this.liveSocket.getActiveElement())\n        if(hook){ hook.__updated() }\n        DOM.deletePrivate(el, PHX_REF)\n      }\n    })\n  }\n\n  putRef(elements, event, opts = {}){\n    let newRef = this.ref++\n    let disableWith = this.binding(PHX_DISABLE_WITH)\n    if(opts.loading){ elements = elements.concat(DOM.all(document, opts.loading))}\n\n    elements.forEach(el => {\n      el.classList.add(`phx-${event}-loading`)\n      el.setAttribute(PHX_REF, newRef)\n      let disableText = el.getAttribute(disableWith)\n      if(disableText !== null){\n        if(!el.getAttribute(PHX_DISABLE_WITH_RESTORE)){\n          el.setAttribute(PHX_DISABLE_WITH_RESTORE, el.innerText)\n        }\n        el.innerText = disableText\n      }\n    })\n    return [newRef, elements, opts]\n  }\n\n  componentID(el){\n    let cid = el.getAttribute && el.getAttribute(PHX_COMPONENT)\n    return cid ? parseInt(cid) : null\n  }\n\n  targetComponentID(target, targetCtx){\n    if(isCid(targetCtx)){ return targetCtx }\n\n    let cidOrSelector = target.getAttribute(this.binding(\"target\"))\n    if(isCid(cidOrSelector)){\n      return parseInt(cidOrSelector)\n    } else if(targetCtx && cidOrSelector !== null){\n      return this.closestComponentID(targetCtx)\n    } else {\n      return null\n    }\n  }\n\n  closestComponentID(targetCtx){\n    if(isCid(targetCtx)){\n      return targetCtx\n    } else if(targetCtx){\n      return maybe(targetCtx.closest(`[${PHX_COMPONENT}]`), el => this.ownsElement(el) && this.componentID(el))\n    } else {\n      return null\n    }\n  }\n\n  pushHookEvent(targetCtx, event, payload, onReply){\n    if(!this.isConnected()){\n      this.log(\"hook\", () => [\"unable to push hook event. LiveView not connected\", event, payload])\n      return false\n    }\n    let [ref, els, opts] = this.putRef([], \"hook\")\n    this.pushWithReply(() => [ref, els, opts], \"event\", {\n      type: \"hook\",\n      event: event,\n      value: payload,\n      cid: this.closestComponentID(targetCtx)\n    }, (resp, reply) => onReply(reply, ref))\n\n    return ref\n  }\n\n  extractMeta(el, meta, value){\n    let prefix = this.binding(\"value-\")\n    for(let i = 0; i < el.attributes.length; i++){\n      if(!meta){ meta = {} }\n      let name = el.attributes[i].name\n      if(name.startsWith(prefix)){ meta[name.replace(prefix, \"\")] = el.getAttribute(name) }\n    }\n    if(el.value !== undefined){\n      if(!meta){ meta = {} }\n      meta.value = el.value\n\n      if(el.tagName === \"INPUT\" && CHECKABLE_INPUTS.indexOf(el.type) >= 0 && !el.checked){\n        delete meta.value\n      }\n    }\n    if(value){\n      if(!meta){ meta = {} }\n      for(let key in value){ meta[key] = value[key] }\n    }\n    return meta\n  }\n\n  pushEvent(type, el, targetCtx, phxEvent, meta, opts = {}){\n    this.pushWithReply(() => this.putRef([el], type, opts), \"event\", {\n      type: type,\n      event: phxEvent,\n      value: this.extractMeta(el, meta, opts.value),\n      cid: this.targetComponentID(el, targetCtx)\n    })\n  }\n\n  pushFileProgress(fileEl, entryRef, progress, onReply = function (){ }){\n    this.liveSocket.withinOwners(fileEl.form, (view, targetCtx) => {\n      view.pushWithReply(null, \"progress\", {\n        event: fileEl.getAttribute(view.binding(PHX_PROGRESS)),\n        ref: fileEl.getAttribute(PHX_UPLOAD_REF),\n        entry_ref: entryRef,\n        progress: progress,\n        cid: view.targetComponentID(fileEl.form, targetCtx)\n      }, onReply)\n    })\n  }\n\n  pushInput(inputEl, targetCtx, forceCid, phxEvent, opts, callback){\n    let uploads\n    let cid = isCid(forceCid) ? forceCid : this.targetComponentID(inputEl.form, targetCtx)\n    let refGenerator = () => this.putRef([inputEl, inputEl.form], \"change\", opts)\n    let formData = serializeForm(inputEl.form, {_target: opts._target})\n    if(DOM.isUploadInput(inputEl) && inputEl.files && inputEl.files.length > 0){\n      LiveUploader.trackFiles(inputEl, Array.from(inputEl.files))\n    }\n    uploads = LiveUploader.serializeUploads(inputEl)\n    let event = {\n      type: \"form\",\n      event: phxEvent,\n      value: formData,\n      uploads: uploads,\n      cid: cid\n    }\n    this.pushWithReply(refGenerator, \"event\", event, resp => {\n      DOM.showError(inputEl, this.liveSocket.binding(PHX_FEEDBACK_FOR))\n      if(DOM.isUploadInput(inputEl) && inputEl.getAttribute(\"data-phx-auto-upload\") !== null){\n        if(LiveUploader.filesAwaitingPreflight(inputEl).length > 0){\n          let [ref, _els] = refGenerator()\n          this.uploadFiles(inputEl.form, targetCtx, ref, cid, (_uploads) => {\n            callback && callback(resp)\n            this.triggerAwaitingSubmit(inputEl.form)\n          })\n        }\n      } else {\n        callback && callback(resp)\n      }\n    })\n  }\n\n  triggerAwaitingSubmit(formEl){\n    let awaitingSubmit = this.getScheduledSubmit(formEl)\n    if(awaitingSubmit){\n      let [_el, _ref, _opts, callback] = awaitingSubmit\n      this.cancelSubmit(formEl)\n      callback()\n    }\n  }\n\n  getScheduledSubmit(formEl){\n    return this.formSubmits.find(([el, _ref, _opts, _callback]) => el.isSameNode(formEl))\n  }\n\n  scheduleSubmit(formEl, ref, opts, callback){\n    if(this.getScheduledSubmit(formEl)){ return true }\n    this.formSubmits.push([formEl, ref, opts, callback])\n  }\n\n  cancelSubmit(formEl){\n    this.formSubmits = this.formSubmits.filter(([el, ref, _callback]) => {\n      if(el.isSameNode(formEl)){\n        this.undoRefs(ref)\n        return false\n      } else {\n        return true\n      }\n    })\n  }\n\n  pushFormSubmit(formEl, targetCtx, phxEvent, opts, onReply){\n    let filterIgnored = el => {\n      let userIgnored = closestPhxBinding(el, `${this.binding(PHX_UPDATE)}=ignore`, el.form)\n      return !(userIgnored || closestPhxBinding(el, \"data-phx-update=ignore\", el.form))\n    }\n    let filterDisables = el => {\n      return el.hasAttribute(this.binding(PHX_DISABLE_WITH))\n    }\n    let filterButton = el => el.tagName == \"BUTTON\"\n\n    let filterInput = el => [\"INPUT\", \"TEXTAREA\", \"SELECT\"].includes(el.tagName)\n\n    let refGenerator = () => {\n      let formElements = Array.from(formEl.elements)\n      let disables = formElements.filter(filterDisables)\n      let buttons = formElements.filter(filterButton).filter(filterIgnored)\n      let inputs = formElements.filter(filterInput).filter(filterIgnored)\n\n      buttons.forEach(button => {\n        button.setAttribute(PHX_DISABLED, button.disabled)\n        button.disabled = true\n      })\n      inputs.forEach(input => {\n        input.setAttribute(PHX_READONLY, input.readOnly)\n        input.readOnly = true\n        if(input.files){\n          input.setAttribute(PHX_DISABLED, input.disabled)\n          input.disabled = true\n        }\n      })\n      formEl.setAttribute(this.binding(PHX_PAGE_LOADING), \"\")\n      return this.putRef([formEl].concat(disables).concat(buttons).concat(inputs), \"submit\", opts)\n    }\n\n    let cid = this.targetComponentID(formEl, targetCtx)\n    if(LiveUploader.hasUploadsInProgress(formEl)){\n      let [ref, _els] = refGenerator()\n      let push = () => this.pushFormSubmit(formEl, targetCtx, phxEvent, opts, onReply)\n      return this.scheduleSubmit(formEl, ref, opts, push)\n    } else if(LiveUploader.inputsAwaitingPreflight(formEl).length > 0){\n      let [ref, els] = refGenerator()\n      let proxyRefGen = () => [ref, els, opts]\n      this.uploadFiles(formEl, targetCtx, ref, cid, (_uploads) => {\n        let formData = serializeForm(formEl, {})\n        this.pushWithReply(proxyRefGen, \"event\", {\n          type: \"form\",\n          event: phxEvent,\n          value: formData,\n          cid: cid\n        }, onReply)\n      })\n    } else {\n      let formData = serializeForm(formEl)\n      this.pushWithReply(refGenerator, \"event\", {\n        type: \"form\",\n        event: phxEvent,\n        value: formData,\n        cid: cid\n      }, onReply)\n    }\n  }\n\n  uploadFiles(formEl, targetCtx, ref, cid, onComplete){\n    let joinCountAtUpload = this.joinCount\n    let inputEls = LiveUploader.activeFileInputs(formEl)\n    let numFileInputsInProgress = inputEls.length\n\n    // get each file input\n    inputEls.forEach(inputEl => {\n      let uploader = new LiveUploader(inputEl, this, () => {\n        numFileInputsInProgress--\n        if(numFileInputsInProgress === 0){ onComplete() }\n      });\n\n      this.uploaders[inputEl] = uploader\n      let entries = uploader.entries().map(entry => entry.toPreflightPayload())\n\n      let payload = {\n        ref: inputEl.getAttribute(PHX_UPLOAD_REF),\n        entries: entries,\n        cid: this.targetComponentID(inputEl.form, targetCtx)\n      }\n\n      this.log(\"upload\", () => [\"sending preflight request\", payload])\n\n      this.pushWithReply(null, \"allow_upload\", payload, resp => {\n        this.log(\"upload\", () => [\"got preflight response\", resp])\n        if(resp.error){\n          this.undoRefs(ref)\n          let [entry_ref, reason] = resp.error\n          this.log(\"upload\", () => [`error for entry ${entry_ref}`, reason])\n        } else {\n          let onError = (callback) => {\n            this.channel.onError(() => {\n              if(this.joinCount === joinCountAtUpload){ callback() }\n            })\n          }\n          uploader.initAdapterUpload(resp, onError, this.liveSocket)\n        }\n      })\n    })\n  }\n\n  dispatchUploads(name, filesOrBlobs){\n    let inputs = DOM.findUploadInputs(this.el).filter(el => el.name === name)\n    if(inputs.length === 0){ logError(`no live file inputs found matching the name \"${name}\"`) }\n    else if(inputs.length > 1){ logError(`duplicate live file inputs found matching the name \"${name}\"`) }\n    else { DOM.dispatchEvent(inputs[0], PHX_TRACK_UPLOADS, {files: filesOrBlobs}) }\n  }\n\n  pushFormRecovery(form, newCid, callback){\n    this.liveSocket.withinOwners(form, (view, targetCtx) => {\n      let input = form.elements[0]\n      let phxEvent = form.getAttribute(this.binding(PHX_AUTO_RECOVER)) || form.getAttribute(this.binding(\"change\"))\n\n      JS.exec(\"change\", phxEvent, view, input, [\"push\", {_target: input.name, newCid: newCid, callback: callback}])\n    })\n  }\n\n  pushLinkPatch(href, targetEl, callback){\n    let linkRef = this.liveSocket.setPendingLink(href)\n    let refGen = targetEl ? () => this.putRef([targetEl], \"click\") : null\n\n    this.pushWithReply(refGen, \"live_patch\", {url: href}, resp => {\n      this.liveSocket.requestDOMUpdate(() => {\n        if(resp.link_redirect){\n          this.liveSocket.replaceMain(href, null, callback, linkRef)\n        } else {\n          if(this.liveSocket.commitPendingLink(linkRef)){\n            this.href = href\n          }\n          this.applyPendingUpdates()\n          callback && callback(linkRef)\n        }\n      })\n    }).receive(\"timeout\", () => this.liveSocket.redirect(window.location.href))\n  }\n\n  formsForRecovery(html){\n    if(this.joinCount === 0){ return [] }\n\n    let phxChange = this.binding(\"change\")\n    let template = document.createElement(\"template\")\n    template.innerHTML = html\n\n    return (\n      DOM.all(this.el, `form[${phxChange}]`)\n        .filter(form => form.id && this.ownsElement(form))\n        .filter(form => form.elements.length > 0)\n        .filter(form => form.getAttribute(this.binding(PHX_AUTO_RECOVER)) !== \"ignore\")\n        .map(form => {\n          let newForm = template.content.querySelector(`form[id=\"${form.id}\"][${phxChange}=\"${form.getAttribute(phxChange)}\"]`)\n          if(newForm){\n            return [form, newForm, this.targetComponentID(newForm)]\n          } else {\n            return [form, null, null]\n          }\n        })\n        .filter(([form, newForm, newCid]) => newForm)\n    )\n  }\n\n  maybePushComponentsDestroyed(destroyedCIDs){\n    let willDestroyCIDs = destroyedCIDs.filter(cid => {\n      return DOM.findComponentNodeList(this.el, cid).length === 0\n    })\n    if(willDestroyCIDs.length > 0){\n      this.pruningCIDs.push(...willDestroyCIDs)\n\n      this.pushWithReply(null, \"cids_will_destroy\", {cids: willDestroyCIDs}, () => {\n        // The cids are either back on the page or they will be fully removed,\n        // so we can remove them from the pruningCIDs.\n        this.pruningCIDs = this.pruningCIDs.filter(cid => willDestroyCIDs.indexOf(cid) !== -1)\n\n        // See if any of the cids we wanted to destroy were added back,\n        // if they were added back, we don't actually destroy them.\n        let completelyDestroyCIDs = willDestroyCIDs.filter(cid => {\n          return DOM.findComponentNodeList(this.el, cid).length === 0\n        })\n\n        if(completelyDestroyCIDs.length > 0){\n          this.pushWithReply(null, \"cids_destroyed\", {cids: completelyDestroyCIDs}, (resp) => {\n            this.rendered.pruneCIDs(resp.cids)\n          })\n        }\n      })\n    }\n  }\n\n  ownsElement(el){\n    return el.getAttribute(PHX_PARENT_ID) === this.id ||\n      maybe(el.closest(PHX_VIEW_SELECTOR), node => node.id) === this.id\n  }\n\n  submitForm(form, targetCtx, phxEvent, opts = {}){\n    DOM.putPrivate(form, PHX_HAS_SUBMITTED, true)\n    this.liveSocket.blurActiveElement(this)\n    this.pushFormSubmit(form, targetCtx, phxEvent, opts, () => {\n      this.liveSocket.restorePreviouslyActiveFocus()\n    })\n  }\n\n  binding(kind){ return this.liveSocket.binding(kind) }\n}\n", "/** Initializes the LiveSocket\n *\n *\n * @param {string} endPoint - The string WebSocket endpoint, ie, `\"wss://example.com/live\"`,\n *                                               `\"/live\"` (inherited host & protocol)\n * @param {Phoenix.Socket} socket - the required Phoenix Socket class imported from \"phoenix\". For example:\n *\n *     import {Socket} from \"phoenix\"\n *     import {LiveSocket} from \"phoenix_live_view\"\n *     let liveSocket = new LiveSocket(\"/live\", Socket, {...})\n *\n * @param {Object} [opts] - Optional configuration. Outside of keys listed below, all\n * configuration is passed directly to the Phoenix Socket constructor.\n * @param {Object} [opts.defaults] - The optional defaults to use for various bindings,\n * such as `phx-debounce`. Supports the following keys:\n *\n *   - debounce - the millisecond phx-debounce time. Defaults 300\n *   - throttle - the millisecond phx-throttle time. Defaults 300\n *\n * @param {Function} [opts.params] - The optional function for passing connect params.\n * The function receives the element associated with a given LiveView. For example:\n *\n *     (el) => {view: el.getAttribute(\"data-my-view-name\", token: window.myToken}\n *\n * @param {string} [opts.bindingPrefix] - The optional prefix to use for all phx DOM annotations.\n * Defaults to \"phx-\".\n * @param {Object} [opts.hooks] - The optional object for referencing LiveView hook callbacks.\n * @param {Object} [opts.uploaders] - The optional object for referencing LiveView uploader callbacks.\n * @param {integer} [opts.loaderTimeout] - The optional delay in milliseconds to wait before apply\n * loading states.\n * @param {Function} [opts.viewLogger] - The optional function to log debug information. For example:\n *\n *     (view, kind, msg, obj) => console.log(`${view.id} ${kind}: ${msg} - `, obj)\n *\n * @param {Object} [opts.metadata] - The optional object mapping event names to functions for\n * populating event metadata. For example:\n *\n *     metadata: {\n *       click: (e, el) => {\n *         return {\n *           ctrlKey: e.ctrlKey,\n *           metaKey: e.metaKey,\n *           detail: e.detail || 1,\n *         }\n *       },\n *       keydown: (e, el) => {\n *         return {\n *           key: e.key,\n *           ctrlKey: e.ctrlKey,\n *           metaKey: e.metaKey,\n *           shiftKey: e.shiftKey\n *         }\n *       }\n *     }\n * @param {Object} [opts.sessionStorage] - An optional Storage compatible object\n * Useful when LiveView won't have access to `sessionStorage`.  For example, This could\n * happen if a site loads a cross-domain LiveView in an iframe.  Example usage:\n *\n *     class InMemoryStorage {\n *       constructor() { this.storage = {} }\n *       getItem(keyName) { return this.storage[keyName] }\n *       removeItem(keyName) { delete this.storage[keyName] }\n *       setItem(keyName, keyValue) { this.storage[keyName] = keyValue }\n *     }\n *\n * @param {Object} [opts.localStorage] - An optional Storage compatible object\n * Useful for when LiveView won't have access to `localStorage`.\n * See `opts.sessionStorage` for examples.\n*/\n\nimport {\n  BINDING_PREFIX,\n  CONSECUTIVE_RELOADS,\n  DEFAULTS,\n  FAILSAFE_JITTER,\n  LOADER_TIMEOUT,\n  MAX_RELOADS,\n  PHX_DEBOUNCE,\n  PHX_DROP_TARGET,\n  PHX_HAS_FOCUSED,\n  PHX_KEY,\n  PHX_LINK_STATE,\n  PHX_LIVE_LINK,\n  PHX_LV_DEBUG,\n  PHX_LV_LATENCY_SIM,\n  PHX_LV_PROFILE,\n  PHX_MAIN,\n  PHX_PARENT_ID,\n  PHX_VIEW_SELECTOR,\n  PHX_ROOT_ID,\n  PHX_THROTTLE,\n  PHX_TRACK_UPLOADS,\n  PHX_SESSION,\n  RELOAD_JITTER,\n} from \"./constants\"\n\nimport {\n  clone,\n  closestPhxBinding,\n  closure,\n  debug,\n  isObject,\n  maybe\n} from \"./utils\"\n\nimport Browser from \"./browser\"\nimport DOM from \"./dom\"\nimport Hooks from \"./hooks\"\nimport LiveUploader from \"./live_uploader\"\nimport View from \"./view\"\nimport JS from \"./js\"\n\nexport default class LiveSocket {\n  constructor(url, phxSocket, opts = {}){\n    this.unloaded = false\n    if(!phxSocket || phxSocket.constructor.name === \"Object\"){\n      throw new Error(`\n      a phoenix Socket must be provided as the second argument to the LiveSocket constructor. For example:\n\n          import {Socket} from \"phoenix\"\n          import LiveSocket from \"phoenix_live_view\"\n          let liveSocket = new LiveSocket(\"/live\", Socket, {...})\n      `)\n    }\n    this.socket = new phxSocket(url, opts)\n    this.bindingPrefix = opts.bindingPrefix || BINDING_PREFIX\n    this.opts = opts\n    this.params = closure(opts.params || {})\n    this.viewLogger = opts.viewLogger\n    this.metadataCallbacks = opts.metadata || {}\n    this.defaults = Object.assign(clone(DEFAULTS), opts.defaults || {})\n    this.activeElement = null\n    this.prevActive = null\n    this.silenced = false\n    this.main = null\n    this.linkRef = 1\n    this.roots = {}\n    this.href = window.location.href\n    this.pendingLink = null\n    this.currentLocation = clone(window.location)\n    this.hooks = opts.hooks || {}\n    this.uploaders = opts.uploaders || {}\n    this.loaderTimeout = opts.loaderTimeout || LOADER_TIMEOUT\n    this.localStorage = opts.localStorage || window.localStorage\n    this.sessionStorage = opts.sessionStorage || window.sessionStorage\n    this.boundTopLevelEvents = false\n    this.domCallbacks = Object.assign({onNodeAdded: closure(), onBeforeElUpdated: closure()}, opts.dom || {})\n    this.transitions = new TransitionSet()\n    window.addEventListener(\"pagehide\", _e => {\n      this.unloaded = true\n    })\n    this.socket.onOpen(() => {\n      if(this.isUnloaded()){\n        // reload page if being restored from back/forward cache and browser does not emit \"pageshow\"\n        window.location.reload()\n      }\n    })\n  }\n\n  // public\n\n  isProfileEnabled(){ return this.sessionStorage.getItem(PHX_LV_PROFILE) === \"true\" }\n\n  isDebugEnabled(){ return this.sessionStorage.getItem(PHX_LV_DEBUG) === \"true\" }\n\n  enableDebug(){ this.sessionStorage.setItem(PHX_LV_DEBUG, \"true\") }\n\n  enableProfiling(){ this.sessionStorage.setItem(PHX_LV_PROFILE, \"true\") }\n\n  disableDebug(){ this.sessionStorage.removeItem(PHX_LV_DEBUG) }\n\n  disableProfiling(){ this.sessionStorage.removeItem(PHX_LV_PROFILE) }\n\n  enableLatencySim(upperBoundMs){\n    this.enableDebug()\n    console.log(\"latency simulator enabled for the duration of this browser session. Call disableLatencySim() to disable\")\n    this.sessionStorage.setItem(PHX_LV_LATENCY_SIM, upperBoundMs)\n  }\n\n  disableLatencySim(){ this.sessionStorage.removeItem(PHX_LV_LATENCY_SIM) }\n\n  getLatencySim(){\n    let str = this.sessionStorage.getItem(PHX_LV_LATENCY_SIM)\n    return str ? parseInt(str) : null\n  }\n\n  getSocket(){ return this.socket }\n\n  connect(){\n    let doConnect = () => {\n      if(this.joinRootViews()){\n        this.bindTopLevelEvents()\n        this.socket.connect()\n      }\n    }\n    if([\"complete\", \"loaded\", \"interactive\"].indexOf(document.readyState) >= 0){\n      doConnect()\n    } else {\n      document.addEventListener(\"DOMContentLoaded\", () => doConnect())\n    }\n  }\n\n  disconnect(callback){ this.socket.disconnect(callback) }\n\n  execJS(el, encodedJS, eventType = null){\n    this.owner(el, view => JS.exec(eventType, encodedJS, view, el))\n  }\n\n  // private\n\n  triggerDOM(kind, args){ this.domCallbacks[kind](...args) }\n\n  time(name, func){\n    if(!this.isProfileEnabled() || !console.time){ return func() }\n    console.time(name)\n    let result = func()\n    console.timeEnd(name)\n    return result\n  }\n\n  log(view, kind, msgCallback){\n    if(this.viewLogger){\n      let [msg, obj] = msgCallback()\n      this.viewLogger(view, kind, msg, obj)\n    } else if(this.isDebugEnabled()){\n      let [msg, obj] = msgCallback()\n      debug(view, kind, msg, obj)\n    }\n  }\n\n  requestDOMUpdate(callback){\n    this.transitions.after(callback)\n  }\n\n  transition(time, onStart, onDone = function(){}){\n    this.transitions.addTransition(time, onStart, onDone)\n  }\n\n  onChannel(channel, event, cb){\n    channel.on(event, data => {\n      let latency = this.getLatencySim()\n      if(!latency){\n        cb(data)\n      } else {\n        console.log(`simulating ${latency}ms of latency from server to client`)\n        setTimeout(() => cb(data), latency)\n      }\n    })\n  }\n\n  wrapPush(view, opts, push){\n    let latency = this.getLatencySim()\n    let oldJoinCount = view.joinCount\n    if(!latency){\n      if(opts.timeout){\n        return push().receive(\"timeout\", () => {\n          if(view.joinCount === oldJoinCount && !view.isDestroyed()){\n            this.reloadWithJitter(view, () => {\n              this.log(view, \"timeout\", () => [\"received timeout while communicating with server. Falling back to hard refresh for recovery\"])\n            })\n          }\n        })\n      } else {\n        return push()\n      }\n    }\n\n    console.log(`simulating ${latency}ms of latency from client to server`)\n    let fakePush = {\n      receives: [],\n      receive(kind, cb){ this.receives.push([kind, cb]) }\n    }\n    setTimeout(() => {\n      if(view.isDestroyed()){ return }\n      fakePush.receives.reduce((acc, [kind, cb]) => acc.receive(kind, cb), push())\n    }, latency)\n    return fakePush\n  }\n\n  reloadWithJitter(view, log){\n    view.destroy()\n    this.disconnect()\n    let [minMs, maxMs] = RELOAD_JITTER\n    let afterMs = Math.floor(Math.random() * (maxMs - minMs + 1)) + minMs\n    let tries = Browser.updateLocal(this.localStorage, window.location.pathname, CONSECUTIVE_RELOADS, 0, count => count + 1)\n    log ? log() : this.log(view, \"join\", () => [`encountered ${tries} consecutive reloads`])\n    if(tries > MAX_RELOADS){\n      this.log(view, \"join\", () => [`exceeded ${MAX_RELOADS} consecutive reloads. Entering failsafe mode`])\n      afterMs = FAILSAFE_JITTER\n    }\n    setTimeout(() => {\n      if(this.hasPendingLink()){\n        window.location = this.pendingLink\n      } else {\n        window.location.reload()\n      }\n    }, afterMs)\n  }\n\n  getHookCallbacks(name){\n    return name && name.startsWith(\"Phoenix.\") ? Hooks[name.split(\".\")[1]] : this.hooks[name]\n  }\n\n  isUnloaded(){ return this.unloaded }\n\n  isConnected(){ return this.socket.isConnected() }\n\n  getBindingPrefix(){ return this.bindingPrefix }\n\n  binding(kind){ return `${this.getBindingPrefix()}${kind}` }\n\n  channel(topic, params){ return this.socket.channel(topic, params) }\n\n  joinRootViews(){\n    let rootsFound = false\n    DOM.all(document, `${PHX_VIEW_SELECTOR}:not([${PHX_PARENT_ID}])`, rootEl => {\n      if(!this.getRootById(rootEl.id)){\n        let view = this.newRootView(rootEl)\n        view.setHref(this.getHref())\n        view.join()\n        if(rootEl.getAttribute(PHX_MAIN)){ this.main = view }\n      }\n      rootsFound = true\n    })\n    return rootsFound\n  }\n\n  redirect(to, flash){\n    this.disconnect()\n    Browser.redirect(to, flash)\n  }\n\n  replaceMain(href, flash, callback = null, linkRef = this.setPendingLink(href)){\n    let oldMainEl = this.main.el\n    let newMainEl = DOM.cloneNode(oldMainEl, \"\")\n    this.main.showLoader(this.loaderTimeout)\n    this.main.destroy()\n\n    this.main = this.newRootView(newMainEl, flash)\n    this.main.setRedirect(href)\n    this.transitionRemoves()\n    this.main.join((joinCount, onDone) => {\n      if(joinCount === 1 && this.commitPendingLink(linkRef)){\n        this.requestDOMUpdate(() => {\n          oldMainEl.replaceWith(newMainEl)\n          callback && callback()\n          onDone()\n        })\n      }\n    })\n  }\n\n  transitionRemoves(elements){\n    let removeAttr = this.binding(\"remove\")\n    elements = elements || DOM.all(document, `[${removeAttr}]`)\n    elements.forEach(el => {\n      if(document.body.contains(el)){ // skip children already removed\n        this.execJS(el, el.getAttribute(removeAttr), \"remove\")\n      }\n    })\n  }\n\n  isPhxView(el){ return el.getAttribute && el.getAttribute(PHX_SESSION) !== null }\n\n  newRootView(el, flash){\n    let view = new View(el, this, null, flash)\n    this.roots[view.id] = view\n    return view\n  }\n\n  owner(childEl, callback){\n    let view = maybe(childEl.closest(PHX_VIEW_SELECTOR), el => this.getViewByEl(el)) || this.main\n    if(view){ callback(view) }\n  }\n\n  withinOwners(childEl, callback){\n    this.owner(childEl, view => callback(view, childEl))\n  }\n\n  getViewByEl(el){\n    let rootId = el.getAttribute(PHX_ROOT_ID)\n    return maybe(this.getRootById(rootId), root => root.getDescendentByEl(el))\n  }\n\n  getRootById(id){ return this.roots[id] }\n\n  destroyAllViews(){\n    for(let id in this.roots){\n      this.roots[id].destroy()\n      delete this.roots[id]\n    }\n  }\n\n  destroyViewByEl(el){\n    let root = this.getRootById(el.getAttribute(PHX_ROOT_ID))\n    if(root){ root.destroyDescendent(el.id) }\n  }\n\n  setActiveElement(target){\n    if(this.activeElement === target){ return }\n    this.activeElement = target\n    let cancel = () => {\n      if(target === this.activeElement){ this.activeElement = null }\n      target.removeEventListener(\"mouseup\", this)\n      target.removeEventListener(\"touchend\", this)\n    }\n    target.addEventListener(\"mouseup\", cancel)\n    target.addEventListener(\"touchend\", cancel)\n  }\n\n  getActiveElement(){\n    if(document.activeElement === document.body){\n      return this.activeElement || document.activeElement\n    } else {\n      // document.activeElement can be null in Internet Explorer 11\n      return document.activeElement || document.body\n    }\n  }\n\n  dropActiveElement(view){\n    if(this.prevActive && view.ownsElement(this.prevActive)){\n      this.prevActive = null\n    }\n  }\n\n  restorePreviouslyActiveFocus(){\n    if(this.prevActive && this.prevActive !== document.body){\n      this.prevActive.focus()\n    }\n  }\n\n  blurActiveElement(){\n    this.prevActive = this.getActiveElement()\n    if(this.prevActive !== document.body){ this.prevActive.blur() }\n  }\n\n  bindTopLevelEvents(){\n    if(this.boundTopLevelEvents){ return }\n\n    this.boundTopLevelEvents = true\n    document.body.addEventListener(\"click\", function (){ }) // ensure all click events bubble for mobile Safari\n    window.addEventListener(\"pageshow\", e => {\n      if(e.persisted){ // reload page if being restored from back/forward cache\n        this.getSocket().disconnect()\n        this.withPageLoading({to: window.location.href, kind: \"redirect\"})\n        window.location.reload()\n      }\n    }, true)\n    this.bindNav()\n    this.bindClicks()\n    this.bindForms()\n    this.bind({keyup: \"keyup\", keydown: \"keydown\"}, (e, type, view, targetEl, phxEvent, eventTarget) => {\n      let matchKey = targetEl.getAttribute(this.binding(PHX_KEY))\n      let pressedKey = e.key && e.key.toLowerCase() // chrome clicked autocompletes send a keydown without key\n      if(matchKey && matchKey.toLowerCase() !== pressedKey){ return }\n\n      let data = {key: e.key, ...this.eventMeta(type, e, targetEl)}\n      JS.exec(type, phxEvent, view, targetEl, [\"push\", {data}])\n    })\n    this.bind({blur: \"focusout\", focus: \"focusin\"}, (e, type, view, targetEl, phxEvent, eventTarget) => {\n      if(!eventTarget){\n        let data = {key: e.key, ...this.eventMeta(type, e, targetEl)}\n        JS.exec(type, phxEvent, view, targetEl, [\"push\", {data}])\n      }\n    })\n    this.bind({blur: \"blur\", focus: \"focus\"}, (e, type, view, targetEl, targetCtx, phxEvent, phxTarget) => {\n      // blur and focus are triggered on document and window. Discard one to avoid dups\n      if(phxTarget === \"window\"){\n        let data = this.eventMeta(type, e, targetEl)\n        JS.exec(type, phxEvent, view, targetEl, [\"push\", {data}])\n      }\n    })\n    window.addEventListener(\"dragover\", e => e.preventDefault())\n    window.addEventListener(\"drop\", e => {\n      e.preventDefault()\n      let dropTargetId = maybe(closestPhxBinding(e.target, this.binding(PHX_DROP_TARGET)), trueTarget => {\n        return trueTarget.getAttribute(this.binding(PHX_DROP_TARGET))\n      })\n      let dropTarget = dropTargetId && document.getElementById(dropTargetId)\n      let files = Array.from(e.dataTransfer.files || [])\n      if(!dropTarget || dropTarget.disabled || files.length === 0 || !(dropTarget.files instanceof FileList)){ return }\n\n      LiveUploader.trackFiles(dropTarget, files)\n      dropTarget.dispatchEvent(new Event(\"input\", {bubbles: true}))\n    })\n    this.on(PHX_TRACK_UPLOADS, e => {\n      let uploadTarget = e.target\n      if(!DOM.isUploadInput(uploadTarget)){ return }\n      let files = Array.from(e.detail.files || []).filter(f => f instanceof File || f instanceof Blob)\n      LiveUploader.trackFiles(uploadTarget, files)\n      uploadTarget.dispatchEvent(new Event(\"input\", {bubbles: true}))\n    })\n  }\n\n  eventMeta(eventName, e, targetEl){\n    let callback = this.metadataCallbacks[eventName]\n    return callback ? callback(e, targetEl) : {}\n  }\n\n  setPendingLink(href){\n    this.linkRef++\n    this.pendingLink = href\n    return this.linkRef\n  }\n\n  commitPendingLink(linkRef){\n    if(this.linkRef !== linkRef){\n      return false\n    } else {\n      this.href = this.pendingLink\n      this.pendingLink = null\n      return true\n    }\n  }\n\n  getHref(){ return this.href }\n\n  hasPendingLink(){ return !!this.pendingLink }\n\n  bind(events, callback){\n    for(let event in events){\n      let browserEventName = events[event]\n\n      this.on(browserEventName, e => {\n        let binding = this.binding(event)\n        let windowBinding = this.binding(`window-${event}`)\n        let targetPhxEvent = e.target.getAttribute && e.target.getAttribute(binding)\n        if(targetPhxEvent){\n          this.debounce(e.target, e, () => {\n            this.withinOwners(e.target, view => {\n              callback(e, event, view, e.target, targetPhxEvent, null)\n            })\n          })\n        } else {\n          DOM.all(document, `[${windowBinding}]`, el => {\n            let phxEvent = el.getAttribute(windowBinding)\n            this.debounce(el, e, () => {\n              this.withinOwners(el, view => {\n                callback(e, event, view, el, phxEvent, \"window\")\n              })\n            })\n          })\n        }\n      })\n    }\n  }\n\n  bindClicks(){\n    this.bindClick(\"click\", \"click\", false)\n    this.bindClick(\"mousedown\", \"capture-click\", true)\n  }\n\n  bindClick(eventName, bindingName, capture){\n    let click = this.binding(bindingName)\n    window.addEventListener(eventName, e => {\n      if(!this.isConnected()){ return }\n      let target = null\n      if(capture){\n        target = e.target.matches(`[${click}]`) ? e.target : e.target.querySelector(`[${click}]`)\n      } else {\n        target = closestPhxBinding(e.target, click)\n        this.dispatchClickAway(e)\n      }\n      let phxEvent = target && target.getAttribute(click)\n      if(!phxEvent){ return }\n      if(target.getAttribute(\"href\") === \"#\"){ e.preventDefault() }\n\n      this.debounce(target, e, () => {\n        this.withinOwners(target, view => {\n          JS.exec(\"click\", phxEvent, view, target, [\"push\", {data: this.eventMeta(\"click\", e, target)}])\n        })\n      })\n    }, capture)\n  }\n\n  dispatchClickAway(e){\n    let binding = this.binding(\"click-away\")\n    DOM.all(document, `[${binding}]`, el => {\n      if(!(el.isSameNode(e.target) || el.contains(e.target))){\n        this.withinOwners(e.target, view => {\n          let phxEvent = el.getAttribute(binding)\n          if(JS.isVisible(el)){\n            JS.exec(\"click\", phxEvent, view, e.target, [\"push\", {data: this.eventMeta(\"click\", e, e.target)}])\n          }\n        })\n      }\n    })\n  }\n\n  bindNav(){\n    if(!Browser.canPushState()){ return }\n    if(history.scrollRestoration){ history.scrollRestoration = \"manual\" }\n    let scrollTimer = null\n    window.addEventListener(\"scroll\", _e => {\n      clearTimeout(scrollTimer)\n      scrollTimer = setTimeout(() => {\n        Browser.updateCurrentState(state => Object.assign(state, {scroll: window.scrollY}))\n      }, 100)\n    })\n    window.addEventListener(\"popstate\", event => {\n      if(!this.registerNewLocation(window.location)){ return }\n      let {type, id, root, scroll} = event.state || {}\n      let href = window.location.href\n\n      this.requestDOMUpdate(() => {\n        if(this.main.isConnected() && (type === \"patch\" && id === this.main.id)){\n          this.main.pushLinkPatch(href, null)\n        } else {\n          this.replaceMain(href, null, () => {\n            if(root){ this.replaceRootHistory() }\n            if(typeof(scroll) === \"number\"){\n              setTimeout(() => {\n                window.scrollTo(0, scroll)\n              }, 0) // the body needs to render before we scroll.\n            }\n          })\n        }\n      })\n    }, false)\n    window.addEventListener(\"click\", e => {\n      let target = closestPhxBinding(e.target, PHX_LIVE_LINK)\n      let type = target && target.getAttribute(PHX_LIVE_LINK)\n      let wantsNewTab = e.metaKey || e.ctrlKey || e.button === 1\n      if(!type || !this.isConnected() || !this.main || wantsNewTab){ return }\n      let href = target.href\n      let linkState = target.getAttribute(PHX_LINK_STATE)\n      e.preventDefault()\n      if(this.pendingLink === href){ return }\n\n      this.requestDOMUpdate(() => {\n        if(type === \"patch\"){\n          this.pushHistoryPatch(href, linkState, target)\n        } else if(type === \"redirect\"){\n          this.historyRedirect(href, linkState)\n        } else {\n          throw new Error(`expected ${PHX_LIVE_LINK} to be \"patch\" or \"redirect\", got: ${type}`)\n        }\n      })\n    }, false)\n  }\n\n  dispatchEvent(event, payload = {}){\n    DOM.dispatchEvent(window, `phx:${event}`, payload)\n  }\n\n  dispatchEvents(events){\n    events.forEach(([event, payload]) => this.dispatchEvent(event, payload))\n  }\n\n  withPageLoading(info, callback){\n    DOM.dispatchEvent(window, \"phx:page-loading-start\", info)\n    let done = () => DOM.dispatchEvent(window, \"phx:page-loading-stop\", info)\n    return callback ? callback(done) : done\n  }\n\n  pushHistoryPatch(href, linkState, targetEl){\n    this.withPageLoading({to: href, kind: \"patch\"}, done => {\n      this.main.pushLinkPatch(href, targetEl, linkRef => {\n        this.historyPatch(href, linkState, linkRef)\n        done()\n      })\n    })\n  }\n\n  historyPatch(href, linkState, linkRef = this.setPendingLink(href)){\n    if(!this.commitPendingLink(linkRef)){ return }\n\n    Browser.pushState(linkState, {type: \"patch\", id: this.main.id}, href)\n    this.registerNewLocation(window.location)\n  }\n\n  historyRedirect(href, linkState, flash){\n    let scroll = window.scrollY\n    this.withPageLoading({to: href, kind: \"redirect\"}, done => {\n      this.replaceMain(href, flash, () => {\n        Browser.pushState(linkState, {type: \"redirect\", id: this.main.id, scroll: scroll}, href)\n        this.registerNewLocation(window.location)\n        done()\n      })\n    })\n  }\n\n  replaceRootHistory(){\n    Browser.pushState(\"replace\", {root: true, type: \"patch\", id: this.main.id})\n  }\n\n  registerNewLocation(newLocation){\n    let {pathname, search} = this.currentLocation\n    if(pathname + search === newLocation.pathname + newLocation.search){\n      return false\n    } else {\n      this.currentLocation = clone(newLocation)\n      return true\n    }\n  }\n\n  bindForms(){\n    let iterations = 0\n    this.on(\"submit\", e => {\n      let phxEvent = e.target.getAttribute(this.binding(\"submit\"))\n      if(!phxEvent){ return }\n      e.preventDefault()\n      e.target.disabled = true\n      this.withinOwners(e.target, view => {\n        JS.exec(\"submit\", phxEvent, view, e.target, [\"push\", {}])\n      })\n    }, false)\n\n    for(let type of [\"change\", \"input\"]){\n      this.on(type, e => {\n        let input = e.target\n        let phxEvent = input.form && input.form.getAttribute(this.binding(\"change\"))\n        if(!phxEvent){ return }\n        if(input.type === \"number\" && input.validity && input.validity.badInput){ return }\n        let currentIterations = iterations\n        iterations++\n        let {at: at, type: lastType} = DOM.private(input, \"prev-iteration\") || {}\n        // detect dup because some browsers dispatch both \"input\" and \"change\"\n        if(at === currentIterations - 1 && type !== lastType){ return }\n\n        DOM.putPrivate(input, \"prev-iteration\", {at: currentIterations, type: type})\n\n        this.debounce(input, e, () => {\n          this.withinOwners(input.form, view => {\n            DOM.putPrivate(input, PHX_HAS_FOCUSED, true)\n            if(!DOM.isTextualInput(input)){\n              this.setActiveElement(input)\n            }\n            JS.exec(\"change\", phxEvent, view, input, [\"push\", {_target: e.target.name}])\n          })\n        })\n      }, false)\n    }\n  }\n\n  debounce(el, event, callback){\n    let phxDebounce = this.binding(PHX_DEBOUNCE)\n    let phxThrottle = this.binding(PHX_THROTTLE)\n    let defaultDebounce = this.defaults.debounce.toString()\n    let defaultThrottle = this.defaults.throttle.toString()\n    DOM.debounce(el, event, phxDebounce, defaultDebounce, phxThrottle, defaultThrottle, callback)\n  }\n\n  silenceEvents(callback){\n    this.silenced = true\n    callback()\n    this.silenced = false\n  }\n\n  on(event, callback){\n    window.addEventListener(event, e => {\n      if(!this.silenced){ callback(e) }\n    })\n  }\n}\n\nclass TransitionSet {\n  constructor(){\n    this.transitions = new Set()\n    this.pendingOps = []\n    this.reset()\n  }\n\n  reset(){\n    this.transitions.forEach(timer => {\n      cancelTimeout(timer)\n      this.transitions.delete(timer)\n    })\n    this.flushPendingOps()\n  }\n\n  after(callback){\n    if(this.size() === 0){\n      callback()\n    } else {\n      this.pushPendingOp(callback)\n    }\n  }\n\n  addTransition(time, onStart, onDone){\n    onStart()\n    let timer = setTimeout(() => {\n      this.transitions.delete(timer)\n      onDone()\n      if(this.size() === 0){ this.flushPendingOps() }\n    }, time)\n    this.transitions.add(timer)\n  }\n\n  pushPendingOp(op){ this.pendingOps.push(op) }\n\n  size(){ return this.transitions.size }\n\n  flushPendingOps(){\n    this.pendingOps.forEach(op => op())\n    this.pendingOps = []\n  }\n}\n", "/**\n * The code in this file is copied from https://github.com/lukeed/clsx and modified to suit the needs of tailwind-merge better.\n *\n * Specifically:\n * - Runtime code from https://github.com/lukeed/clsx/blob/v1.2.1/src/index.js\n * - TypeScript types from https://github.com/lukeed/clsx/blob/v1.2.1/clsx.d.ts\n *\n * Original code has MIT license: Copyright (c) Luke Edwards <luke.edwards05@gmail.com> (lukeed.com)\n */\n\nexport type ClassNameValue = ClassNameArray | string | null | undefined | 0 | false\ntype ClassNameArray = ClassNameValue[]\n\nexport function twJoin(...classLists: ClassNameValue[]): string\nexport function twJoin() {\n    let index = 0\n    let argument: ClassNameValue\n    let resolvedValue: string\n    let string = ''\n\n    while (index < arguments.length) {\n        if ((argument = arguments[index++])) {\n            if ((resolvedValue = toValue(argument))) {\n                string && (string += ' ')\n                string += resolvedValue\n            }\n        }\n    }\n    return string\n}\n\nfunction toValue(mix: ClassNameArray | string) {\n    if (typeof mix === 'string') {\n        return mix\n    }\n\n    let resolvedValue: string\n    let string = ''\n\n    for (let k = 0; k < mix.length; k++) {\n        if (mix[k]) {\n            if ((resolvedValue = toValue(mix[k] as ClassNameArray | string))) {\n                string && (string += ' ')\n                string += resolvedValue\n            }\n        }\n    }\n\n    return string\n}\n", "function _extends() {\n  _extends = Object.assign ? Object.assign.bind() : function (target) {\n    for (var i = 1; i < arguments.length; i++) {\n      var source = arguments[i];\n      for (var key in source) {\n        if (Object.prototype.hasOwnProperty.call(source, key)) {\n          target[key] = source[key];\n        }\n      }\n    }\n    return target;\n  };\n  return _extends.apply(this, arguments);\n}\n\nexport { _extends as extends };\n//# sourceMappingURL=_rollupPluginBabelHelpers.mjs.map\n", "import { ClassGroup, ClassGroupId, ClassValidator, Config, ThemeGetter, ThemeObject } from './types'\n\nexport interface ClassPartObject {\n    nextPart: Map<string, ClassPartObject>\n    validators: ClassValidatorObject[]\n    classGroupId?: ClassGroupId\n}\n\ninterface ClassValidatorObject {\n    classGroupId: ClassGroupId\n    validator: ClassValidator\n}\n\nconst CLASS_PART_SEPARATOR = '-'\n\nexport function createClassUtils(config: Config) {\n    const classMap = createClassMap(config)\n\n    function getClassGroupId(className: string) {\n        const classParts = className.split(CLASS_PART_SEPARATOR)\n\n        // Classes like `-inset-1` produce an empty string as first classPart. We assume that classes for negative values are used correctly and remove it from classParts.\n        if (classParts[0] === '' && classParts.length !== 1) {\n            classParts.shift()\n        }\n\n        return getGroupRecursive(classParts, classMap) || getGroupIdForArbitraryProperty(className)\n    }\n\n    function getConflictingClassGroupIds(classGroupId: ClassGroupId) {\n        return config.conflictingClassGroups[classGroupId] || []\n    }\n\n    return {\n        getClassGroupId,\n        getConflictingClassGroupIds,\n    }\n}\n\nfunction getGroupRecursive(\n    classParts: string[],\n    classPartObject: ClassPartObject,\n): ClassGroupId | undefined {\n    if (classParts.length === 0) {\n        return classPartObject.classGroupId\n    }\n\n    const currentClassPart = classParts[0]!\n    const nextClassPartObject = classPartObject.nextPart.get(currentClassPart)\n    const classGroupFromNextClassPart = nextClassPartObject\n        ? getGroupRecursive(classParts.slice(1), nextClassPartObject)\n        : undefined\n\n    if (classGroupFromNextClassPart) {\n        return classGroupFromNextClassPart\n    }\n\n    if (classPartObject.validators.length === 0) {\n        return undefined\n    }\n\n    const classRest = classParts.join(CLASS_PART_SEPARATOR)\n\n    return classPartObject.validators.find(({ validator }) => validator(classRest))?.classGroupId\n}\n\nconst arbitraryPropertyRegex = /^\\[(.+)\\]$/\n\nfunction getGroupIdForArbitraryProperty(className: string) {\n    if (arbitraryPropertyRegex.test(className)) {\n        const arbitraryPropertyClassName = arbitraryPropertyRegex.exec(className)![1]\n        const property = arbitraryPropertyClassName?.substring(\n            0,\n            arbitraryPropertyClassName.indexOf(':'),\n        )\n\n        if (property) {\n            // I use two dots here because one dot is used as prefix for class groups in plugins\n            return 'arbitrary..' + property\n        }\n    }\n}\n\n/**\n * Exported for testing only\n */\nexport function createClassMap(config: Config) {\n    const { theme, prefix } = config\n    const classMap: ClassPartObject = {\n        nextPart: new Map<string, ClassPartObject>(),\n        validators: [],\n    }\n\n    const prefixedClassGroupEntries = getPrefixedClassGroupEntries(\n        Object.entries(config.classGroups),\n        prefix,\n    )\n\n    prefixedClassGroupEntries.forEach(([classGroupId, classGroup]) => {\n        processClassesRecursively(classGroup, classMap, classGroupId, theme)\n    })\n\n    return classMap\n}\n\nfunction processClassesRecursively(\n    classGroup: ClassGroup,\n    classPartObject: ClassPartObject,\n    classGroupId: ClassGroupId,\n    theme: ThemeObject,\n) {\n    classGroup.forEach((classDefinition) => {\n        if (typeof classDefinition === 'string') {\n            const classPartObjectToEdit =\n                classDefinition === '' ? classPartObject : getPart(classPartObject, classDefinition)\n            classPartObjectToEdit.classGroupId = classGroupId\n            return\n        }\n\n        if (typeof classDefinition === 'function') {\n            if (isThemeGetter(classDefinition)) {\n                processClassesRecursively(\n                    classDefinition(theme),\n                    classPartObject,\n                    classGroupId,\n                    theme,\n                )\n                return\n            }\n\n            classPartObject.validators.push({\n                validator: classDefinition,\n                classGroupId,\n            })\n\n            return\n        }\n\n        Object.entries(classDefinition).forEach(([key, classGroup]) => {\n            processClassesRecursively(\n                classGroup,\n                getPart(classPartObject, key),\n                classGroupId,\n                theme,\n            )\n        })\n    })\n}\n\nfunction getPart(classPartObject: ClassPartObject, path: string) {\n    let currentClassPartObject = classPartObject\n\n    path.split(CLASS_PART_SEPARATOR).forEach((pathPart) => {\n        if (!currentClassPartObject.nextPart.has(pathPart)) {\n            currentClassPartObject.nextPart.set(pathPart, {\n                nextPart: new Map(),\n                validators: [],\n            })\n        }\n\n        currentClassPartObject = currentClassPartObject.nextPart.get(pathPart)!\n    })\n\n    return currentClassPartObject\n}\n\nfunction isThemeGetter(func: ClassValidator | ThemeGetter): func is ThemeGetter {\n    return (func as ThemeGetter).isThemeGetter\n}\n\nfunction getPrefixedClassGroupEntries(\n    classGroupEntries: Array<[classGroupId: string, classGroup: ClassGroup]>,\n    prefix: string | undefined,\n): Array<[classGroupId: string, classGroup: ClassGroup]> {\n    if (!prefix) {\n        return classGroupEntries\n    }\n\n    return classGroupEntries.map(([classGroupId, classGroup]) => {\n        const prefixedClassGroup = classGroup.map((classDefinition) => {\n            if (typeof classDefinition === 'string') {\n                return prefix + classDefinition\n            }\n\n            if (typeof classDefinition === 'object') {\n                return Object.fromEntries(\n                    Object.entries(classDefinition).map(([key, value]) => [prefix + key, value]),\n                )\n            }\n\n            return classDefinition\n        })\n\n        return [classGroupId, prefixedClassGroup]\n    })\n}\n", "// Export is needed because TypeScript complains about an error otherwise:\n// Error: \u2026/tailwind-merge/src/config-utils.ts(8,17): semantic error TS4058: Return type of exported function has or is using name 'LruCache' from external module \"\u2026/tailwind-merge/src/lru-cache\" but cannot be named.\nexport interface LruCache<Key, Value> {\n    get(key: Key): Value | undefined\n    set(key: Key, value: Value): void\n}\n\n// LRU cache inspired from hashlru (https://github.com/dominictarr/hashlru/blob/v1.0.4/index.js) but object replaced with Map to improve performance\nexport function createLruCache<Key, Value>(maxCacheSize: number): LruCache<Key, Value> {\n    if (maxCacheSize < 1) {\n        return {\n            get: () => undefined,\n            set: () => {},\n        }\n    }\n\n    let cacheSize = 0\n    let cache = new Map<Key, Value>()\n    let previousCache = new Map<Key, Value>()\n\n    function update(key: Key, value: Value) {\n        cache.set(key, value)\n        cacheSize++\n\n        if (cacheSize > maxCacheSize) {\n            cacheSize = 0\n            previousCache = cache\n            cache = new Map()\n        }\n    }\n\n    return {\n        get(key) {\n            let value = cache.get(key)\n\n            if (value !== undefined) {\n                return value\n            }\n            if ((value = previousCache.get(key)) !== undefined) {\n                update(key, value)\n                return value\n            }\n        },\n        set(key, value) {\n            if (cache.has(key)) {\n                cache.set(key, value)\n            } else {\n                update(key, value)\n            }\n        },\n    }\n}\n", "import { Config } from './types'\n\nexport const IMPORTANT_MODIFIER = '!'\n\nexport function createSplitModifiers(config: Config) {\n    const separator = config.separator || ':'\n\n    // splitModifiers inspired by https://github.com/tailwindlabs/tailwindcss/blob/v3.2.2/src/util/splitAtTopLevelOnly.js\n    return function splitModifiers(className: string) {\n        let bracketDepth = 0\n        let modifiers = []\n        let modifierStart = 0\n\n        for (let index = 0; index < className.length; index++) {\n            let char = className[index]\n\n            if (bracketDepth === 0 && char === separator[0]) {\n                if (\n                    separator.length === 1 ||\n                    className.slice(index, index + separator.length) === separator\n                ) {\n                    modifiers.push(className.slice(modifierStart, index))\n                    modifierStart = index + separator.length\n                }\n            }\n\n            if (char === '[') {\n                bracketDepth++\n            } else if (char === ']') {\n                bracketDepth--\n            }\n        }\n\n        const baseClassNameWithImportantModifier =\n            modifiers.length === 0 ? className : className.substring(modifierStart)\n        const hasImportantModifier =\n            baseClassNameWithImportantModifier.startsWith(IMPORTANT_MODIFIER)\n        const baseClassName = hasImportantModifier\n            ? baseClassNameWithImportantModifier.substring(1)\n            : baseClassNameWithImportantModifier\n\n        return {\n            modifiers,\n            hasImportantModifier,\n            baseClassName,\n        }\n    }\n}\n\n/**\n * Sorts modifiers according to following schema:\n * - Predefined modifiers are sorted alphabetically\n * - When an arbitrary variant appears, it must be preserved which modifiers are before and after it\n */\nexport function sortModifiers(modifiers: string[]) {\n    if (modifiers.length <= 1) {\n        return modifiers\n    }\n\n    const sortedModifiers: string[] = []\n    let unsortedModifiers: string[] = []\n\n    modifiers.forEach((modifier) => {\n        const isArbitraryVariant = modifier[0] === '['\n\n        if (isArbitraryVariant) {\n            sortedModifiers.push(...unsortedModifiers.sort(), modifier)\n            unsortedModifiers = []\n        } else {\n            unsortedModifiers.push(modifier)\n        }\n    })\n\n    sortedModifiers.push(...unsortedModifiers.sort())\n\n    return sortedModifiers\n}\n", "import { createClassUtils } from './class-utils'\nimport { createLruCache } from './lru-cache'\nimport { createSplitModifiers } from './modifier-utils'\nimport { Config } from './types'\n\nexport type ConfigUtils = ReturnType<typeof createConfigUtils>\n\nexport function createConfigUtils(config: Config) {\n    return {\n        cache: createLruCache<string, string>(config.cacheSize),\n        splitModifiers: createSplitModifiers(config),\n        ...createClassUtils(config),\n    }\n}\n", "import { ConfigUtils } from './config-utils'\nimport { IMPORTANT_MODIFIER, sortModifiers } from './modifier-utils'\n\nconst SPLIT_CLASSES_REGEX = /\\s+/\n\nexport function mergeClassList(classList: string, configUtils: ConfigUtils) {\n    const { splitModifiers, getClassGroupId, getConflictingClassGroupIds } = configUtils\n\n    /**\n     * Set of classGroupIds in following format:\n     * `{importantModifier}{variantModifiers}{classGroupId}`\n     * @example 'float'\n     * @example 'hover:focus:bg-color'\n     * @example 'md:!pr'\n     */\n    const classGroupsInConflict = new Set<string>()\n\n    return (\n        classList\n            .trim()\n            .split(SPLIT_CLASSES_REGEX)\n            .map((originalClassName) => {\n                const { modifiers, hasImportantModifier, baseClassName } =\n                    splitModifiers(originalClassName)\n\n                const classGroupId = getClassGroupId(baseClassName)\n\n                if (!classGroupId) {\n                    return {\n                        isTailwindClass: false as const,\n                        originalClassName,\n                    }\n                }\n\n                const variantModifier = sortModifiers(modifiers).join(':')\n\n                const modifierId = hasImportantModifier\n                    ? variantModifier + IMPORTANT_MODIFIER\n                    : variantModifier\n\n                return {\n                    isTailwindClass: true as const,\n                    modifierId,\n                    classGroupId,\n                    originalClassName,\n                }\n            })\n            .reverse()\n            // Last class in conflict wins, so we need to filter conflicting classes in reverse order.\n            .filter((parsed) => {\n                if (!parsed.isTailwindClass) {\n                    return true\n                }\n\n                const { modifierId, classGroupId } = parsed\n\n                const classId = modifierId + classGroupId\n\n                if (classGroupsInConflict.has(classId)) {\n                    return false\n                }\n\n                classGroupsInConflict.add(classId)\n\n                getConflictingClassGroupIds(classGroupId).forEach((group) =>\n                    classGroupsInConflict.add(modifierId + group),\n                )\n\n                return true\n            })\n            .reverse()\n            .map((parsed) => parsed.originalClassName)\n            .join(' ')\n    )\n}\n", "import { createConfigUtils } from './config-utils'\nimport { mergeClassList } from './merge-classlist'\nimport { ClassNameValue, twJoin } from './tw-join'\nimport { Config } from './types'\n\ntype CreateConfigFirst = () => Config\ntype CreateConfigSubsequent = (config: Config) => Config\ntype TailwindMerge = (...classLists: ClassNameValue[]) => string\ntype ConfigUtils = ReturnType<typeof createConfigUtils>\n\nexport function createTailwindMerge(\n    ...createConfig: [CreateConfigFirst, ...CreateConfigSubsequent[]]\n): TailwindMerge {\n    let configUtils: ConfigUtils\n    let cacheGet: ConfigUtils['cache']['get']\n    let cacheSet: ConfigUtils['cache']['set']\n    let functionToCall = initTailwindMerge\n\n    function initTailwindMerge(classList: string) {\n        const [firstCreateConfig, ...restCreateConfig] = createConfig\n\n        const config = restCreateConfig.reduce(\n            (previousConfig, createConfigCurrent) => createConfigCurrent(previousConfig),\n            firstCreateConfig(),\n        )\n\n        configUtils = createConfigUtils(config)\n        cacheGet = configUtils.cache.get\n        cacheSet = configUtils.cache.set\n        functionToCall = tailwindMerge\n\n        return tailwindMerge(classList)\n    }\n\n    function tailwindMerge(classList: string) {\n        const cachedResult = cacheGet(classList)\n\n        if (cachedResult) {\n            return cachedResult\n        }\n\n        const result = mergeClassList(classList, configUtils)\n        cacheSet(classList, result)\n\n        return result\n    }\n\n    return function callTailwindMerge() {\n        return functionToCall(twJoin.apply(null, arguments as any))\n    }\n}\n", "import { ThemeGetter, ThemeObject } from './types'\n\nexport function fromTheme(key: string): ThemeGetter {\n    const themeGetter = (theme: ThemeObject) => theme[key] || []\n\n    themeGetter.isThemeGetter = true as const\n\n    return themeGetter\n}\n", "const arbitraryValueRegex = /^\\[(?:([a-z-]+):)?(.+)\\]$/i\nconst fractionRegex = /^\\d+\\/\\d+$/\nconst stringLengths = new Set(['px', 'full', 'screen'])\nconst tshirtUnitRegex = /^(\\d+(\\.\\d+)?)?(xs|sm|md|lg|xl)$/\nconst lengthUnitRegex = /\\d+(%|px|r?em|[sdl]?v([hwib]|min|max)|pt|pc|in|cm|mm|cap|ch|ex|r?lh|cq(w|h|i|b|min|max))/\n// Shadow always begins with x and y offset separated by underscore\nconst shadowRegex = /^-?((\\d+)?\\.?(\\d+)[a-z]+|0)_-?((\\d+)?\\.?(\\d+)[a-z]+|0)/\n\nexport function isLength(value: string) {\n    return (\n        isNumber(value) ||\n        stringLengths.has(value) ||\n        fractionRegex.test(value) ||\n        isArbitraryLength(value)\n    )\n}\n\nexport function isArbitraryLength(value: string) {\n    return getIsArbitraryValue(value, 'length', isLengthOnly)\n}\n\nexport function isArbitrarySize(value: string) {\n    return getIsArbitraryValue(value, 'size', isNever)\n}\n\nexport function isArbitraryPosition(value: string) {\n    return getIsArbitraryValue(value, 'position', isNever)\n}\n\nexport function isArbitraryUrl(value: string) {\n    return getIsArbitraryValue(value, 'url', isUrl)\n}\n\nexport function isArbitraryNumber(value: string) {\n    return getIsArbitraryValue(value, 'number', isNumber)\n}\n\n/**\n * @deprecated Will be removed in next major version. Use `isArbitraryNumber` instead.\n */\nexport const isArbitraryWeight = isArbitraryNumber\n\nexport function isNumber(value: string) {\n    return !Number.isNaN(Number(value))\n}\n\nexport function isInteger(value: string) {\n    return isIntegerOnly(value) || getIsArbitraryValue(value, 'number', isIntegerOnly)\n}\n\nexport function isArbitraryValue(value: string) {\n    return arbitraryValueRegex.test(value)\n}\n\nexport function isAny() {\n    return true\n}\n\nexport function isTshirtSize(value: string) {\n    return tshirtUnitRegex.test(value)\n}\n\nexport function isArbitraryShadow(value: string) {\n    return getIsArbitraryValue(value, '', isShadow)\n}\n\nfunction getIsArbitraryValue(value: string, label: string, testValue: (value: string) => boolean) {\n    const result = arbitraryValueRegex.exec(value)\n\n    if (result) {\n        if (result[1]) {\n            return result[1] === label\n        }\n\n        return testValue(result[2]!)\n    }\n\n    return false\n}\n\nfunction isLengthOnly(value: string) {\n    return lengthUnitRegex.test(value)\n}\n\nfunction isNever() {\n    return false\n}\n\nfunction isUrl(value: string) {\n    return value.startsWith('url(')\n}\n\nfunction isIntegerOnly(value: string) {\n    return Number.isInteger(Number(value))\n}\n\nfunction isShadow(value: string) {\n    return shadowRegex.test(value)\n}\n", "import { fromTheme } from './from-theme'\nimport {\n    isAny,\n    isArbitraryLength,\n    isArbitraryNumber,\n    isArbitraryPosition,\n    isArbitraryShadow,\n    isArbitrarySize,\n    isArbitraryUrl,\n    isArbitraryValue,\n    isInteger,\n    isLength,\n    isNumber,\n    isTshirtSize,\n} from './validators'\n\nexport function getDefaultConfig() {\n    const colors = fromTheme('colors')\n    const spacing = fromTheme('spacing')\n    const blur = fromTheme('blur')\n    const brightness = fromTheme('brightness')\n    const borderColor = fromTheme('borderColor')\n    const borderRadius = fromTheme('borderRadius')\n    const borderSpacing = fromTheme('borderSpacing')\n    const borderWidth = fromTheme('borderWidth')\n    const contrast = fromTheme('contrast')\n    const grayscale = fromTheme('grayscale')\n    const hueRotate = fromTheme('hueRotate')\n    const invert = fromTheme('invert')\n    const gap = fromTheme('gap')\n    const gradientColorStops = fromTheme('gradientColorStops')\n    const inset = fromTheme('inset')\n    const margin = fromTheme('margin')\n    const opacity = fromTheme('opacity')\n    const padding = fromTheme('padding')\n    const saturate = fromTheme('saturate')\n    const scale = fromTheme('scale')\n    const sepia = fromTheme('sepia')\n    const skew = fromTheme('skew')\n    const space = fromTheme('space')\n    const translate = fromTheme('translate')\n\n    const getOverscroll = () => ['auto', 'contain', 'none'] as const\n    const getOverflow = () => ['auto', 'hidden', 'clip', 'visible', 'scroll'] as const\n    const getSpacingWithAuto = () => ['auto', spacing] as const\n    const getLengthWithEmpty = () => ['', isLength] as const\n    const getNumberWithAutoAndArbitrary = () => ['auto', isNumber, isArbitraryValue] as const\n    const getPositions = () =>\n        [\n            'bottom',\n            'center',\n            'left',\n            'left-bottom',\n            'left-top',\n            'right',\n            'right-bottom',\n            'right-top',\n            'top',\n        ] as const\n    const getLineStyles = () => ['solid', 'dashed', 'dotted', 'double', 'none'] as const\n    const getBlendModes = () =>\n        [\n            'normal',\n            'multiply',\n            'screen',\n            'overlay',\n            'darken',\n            'lighten',\n            'color-dodge',\n            'color-burn',\n            'hard-light',\n            'soft-light',\n            'difference',\n            'exclusion',\n            'hue',\n            'saturation',\n            'color',\n            'luminosity',\n            'plus-lighter',\n        ] as const\n    const getAlign = () => ['start', 'end', 'center', 'between', 'around', 'evenly'] as const\n    const getZeroAndEmpty = () => ['', '0', isArbitraryValue] as const\n    const getBreaks = () =>\n        ['auto', 'avoid', 'all', 'avoid-page', 'page', 'left', 'right', 'column'] as const\n    const getNumber = () => [isNumber, isArbitraryNumber]\n    const getNumberAndArbitrary = () => [isNumber, isArbitraryValue]\n\n    return {\n        cacheSize: 500,\n        theme: {\n            colors: [isAny],\n            spacing: [isLength],\n            blur: ['none', '', isTshirtSize, isArbitraryLength],\n            brightness: getNumber(),\n            borderColor: [colors],\n            borderRadius: ['none', '', 'full', isTshirtSize, isArbitraryLength],\n            borderSpacing: [spacing],\n            borderWidth: getLengthWithEmpty(),\n            contrast: getNumber(),\n            grayscale: getZeroAndEmpty(),\n            hueRotate: getNumberAndArbitrary(),\n            invert: getZeroAndEmpty(),\n            gap: [spacing],\n            gradientColorStops: [colors],\n            inset: getSpacingWithAuto(),\n            margin: getSpacingWithAuto(),\n            opacity: getNumber(),\n            padding: [spacing],\n            saturate: getNumber(),\n            scale: getNumber(),\n            sepia: getZeroAndEmpty(),\n            skew: getNumberAndArbitrary(),\n            space: [spacing],\n            translate: [spacing],\n        },\n        classGroups: {\n            // Layout\n            /**\n             * Aspect Ratio\n             * @see https://tailwindcss.com/docs/aspect-ratio\n             */\n            aspect: [{ aspect: ['auto', 'square', 'video', isArbitraryValue] }],\n            /**\n             * Container\n             * @see https://tailwindcss.com/docs/container\n             */\n            container: ['container'],\n            /**\n             * Columns\n             * @see https://tailwindcss.com/docs/columns\n             */\n            columns: [{ columns: [isTshirtSize] }],\n            /**\n             * Break After\n             * @see https://tailwindcss.com/docs/break-after\n             */\n            'break-after': [{ 'break-after': getBreaks() }],\n            /**\n             * Break Before\n             * @see https://tailwindcss.com/docs/break-before\n             */\n            'break-before': [{ 'break-before': getBreaks() }],\n            /**\n             * Break Inside\n             * @see https://tailwindcss.com/docs/break-inside\n             */\n            'break-inside': [{ 'break-inside': ['auto', 'avoid', 'avoid-page', 'avoid-column'] }],\n            /**\n             * Box Decoration Break\n             * @see https://tailwindcss.com/docs/box-decoration-break\n             */\n            'box-decoration': [{ 'box-decoration': ['slice', 'clone'] }],\n            /**\n             * Box Sizing\n             * @see https://tailwindcss.com/docs/box-sizing\n             */\n            box: [{ box: ['border', 'content'] }],\n            /**\n             * Display\n             * @see https://tailwindcss.com/docs/display\n             */\n            display: [\n                'block',\n                'inline-block',\n                'inline',\n                'flex',\n                'inline-flex',\n                'table',\n                'inline-table',\n                'table-caption',\n                'table-cell',\n                'table-column',\n                'table-column-group',\n                'table-footer-group',\n                'table-header-group',\n                'table-row-group',\n                'table-row',\n                'flow-root',\n                'grid',\n                'inline-grid',\n                'contents',\n                'list-item',\n                'hidden',\n            ],\n            /**\n             * Floats\n             * @see https://tailwindcss.com/docs/float\n             */\n            float: [{ float: ['right', 'left', 'none'] }],\n            /**\n             * Clear\n             * @see https://tailwindcss.com/docs/clear\n             */\n            clear: [{ clear: ['left', 'right', 'both', 'none'] }],\n            /**\n             * Isolation\n             * @see https://tailwindcss.com/docs/isolation\n             */\n            isolation: ['isolate', 'isolation-auto'],\n            /**\n             * Object Fit\n             * @see https://tailwindcss.com/docs/object-fit\n             */\n            'object-fit': [{ object: ['contain', 'cover', 'fill', 'none', 'scale-down'] }],\n            /**\n             * Object Position\n             * @see https://tailwindcss.com/docs/object-position\n             */\n            'object-position': [{ object: [...getPositions(), isArbitraryValue] }],\n            /**\n             * Overflow\n             * @see https://tailwindcss.com/docs/overflow\n             */\n            overflow: [{ overflow: getOverflow() }],\n            /**\n             * Overflow X\n             * @see https://tailwindcss.com/docs/overflow\n             */\n            'overflow-x': [{ 'overflow-x': getOverflow() }],\n            /**\n             * Overflow Y\n             * @see https://tailwindcss.com/docs/overflow\n             */\n            'overflow-y': [{ 'overflow-y': getOverflow() }],\n            /**\n             * Overscroll Behavior\n             * @see https://tailwindcss.com/docs/overscroll-behavior\n             */\n            overscroll: [{ overscroll: getOverscroll() }],\n            /**\n             * Overscroll Behavior X\n             * @see https://tailwindcss.com/docs/overscroll-behavior\n             */\n            'overscroll-x': [{ 'overscroll-x': getOverscroll() }],\n            /**\n             * Overscroll Behavior Y\n             * @see https://tailwindcss.com/docs/overscroll-behavior\n             */\n            'overscroll-y': [{ 'overscroll-y': getOverscroll() }],\n            /**\n             * Position\n             * @see https://tailwindcss.com/docs/position\n             */\n            position: ['static', 'fixed', 'absolute', 'relative', 'sticky'],\n            /**\n             * Top / Right / Bottom / Left\n             * @see https://tailwindcss.com/docs/top-right-bottom-left\n             */\n            inset: [{ inset: [inset] }],\n            /**\n             * Right / Left\n             * @see https://tailwindcss.com/docs/top-right-bottom-left\n             */\n            'inset-x': [{ 'inset-x': [inset] }],\n            /**\n             * Top / Bottom\n             * @see https://tailwindcss.com/docs/top-right-bottom-left\n             */\n            'inset-y': [{ 'inset-y': [inset] }],\n            /**\n             * Top\n             * @see https://tailwindcss.com/docs/top-right-bottom-left\n             */\n            top: [{ top: [inset] }],\n            /**\n             * Right\n             * @see https://tailwindcss.com/docs/top-right-bottom-left\n             */\n            right: [{ right: [inset] }],\n            /**\n             * Bottom\n             * @see https://tailwindcss.com/docs/top-right-bottom-left\n             */\n            bottom: [{ bottom: [inset] }],\n            /**\n             * Left\n             * @see https://tailwindcss.com/docs/top-right-bottom-left\n             */\n            left: [{ left: [inset] }],\n            /**\n             * Visibility\n             * @see https://tailwindcss.com/docs/visibility\n             */\n            visibility: ['visible', 'invisible', 'collapse'],\n            /**\n             * Z-Index\n             * @see https://tailwindcss.com/docs/z-index\n             */\n            z: [{ z: ['auto', isInteger] }],\n            // Flexbox and Grid\n            /**\n             * Flex Basis\n             * @see https://tailwindcss.com/docs/flex-basis\n             */\n            basis: [{ basis: [spacing] }],\n            /**\n             * Flex Direction\n             * @see https://tailwindcss.com/docs/flex-direction\n             */\n            'flex-direction': [{ flex: ['row', 'row-reverse', 'col', 'col-reverse'] }],\n            /**\n             * Flex Wrap\n             * @see https://tailwindcss.com/docs/flex-wrap\n             */\n            'flex-wrap': [{ flex: ['wrap', 'wrap-reverse', 'nowrap'] }],\n            /**\n             * Flex\n             * @see https://tailwindcss.com/docs/flex\n             */\n            flex: [{ flex: ['1', 'auto', 'initial', 'none', isArbitraryValue] }],\n            /**\n             * Flex Grow\n             * @see https://tailwindcss.com/docs/flex-grow\n             */\n            grow: [{ grow: getZeroAndEmpty() }],\n            /**\n             * Flex Shrink\n             * @see https://tailwindcss.com/docs/flex-shrink\n             */\n            shrink: [{ shrink: getZeroAndEmpty() }],\n            /**\n             * Order\n             * @see https://tailwindcss.com/docs/order\n             */\n            order: [{ order: ['first', 'last', 'none', isInteger] }],\n            /**\n             * Grid Template Columns\n             * @see https://tailwindcss.com/docs/grid-template-columns\n             */\n            'grid-cols': [{ 'grid-cols': [isAny] }],\n            /**\n             * Grid Column Start / End\n             * @see https://tailwindcss.com/docs/grid-column\n             */\n            'col-start-end': [{ col: ['auto', { span: [isInteger] }, isArbitraryValue] }],\n            /**\n             * Grid Column Start\n             * @see https://tailwindcss.com/docs/grid-column\n             */\n            'col-start': [{ 'col-start': getNumberWithAutoAndArbitrary() }],\n            /**\n             * Grid Column End\n             * @see https://tailwindcss.com/docs/grid-column\n             */\n            'col-end': [{ 'col-end': getNumberWithAutoAndArbitrary() }],\n            /**\n             * Grid Template Rows\n             * @see https://tailwindcss.com/docs/grid-template-rows\n             */\n            'grid-rows': [{ 'grid-rows': [isAny] }],\n            /**\n             * Grid Row Start / End\n             * @see https://tailwindcss.com/docs/grid-row\n             */\n            'row-start-end': [{ row: ['auto', { span: [isInteger] }, isArbitraryValue] }],\n            /**\n             * Grid Row Start\n             * @see https://tailwindcss.com/docs/grid-row\n             */\n            'row-start': [{ 'row-start': getNumberWithAutoAndArbitrary() }],\n            /**\n             * Grid Row End\n             * @see https://tailwindcss.com/docs/grid-row\n             */\n            'row-end': [{ 'row-end': getNumberWithAutoAndArbitrary() }],\n            /**\n             * Grid Auto Flow\n             * @see https://tailwindcss.com/docs/grid-auto-flow\n             */\n            'grid-flow': [{ 'grid-flow': ['row', 'col', 'dense', 'row-dense', 'col-dense'] }],\n            /**\n             * Grid Auto Columns\n             * @see https://tailwindcss.com/docs/grid-auto-columns\n             */\n            'auto-cols': [{ 'auto-cols': ['auto', 'min', 'max', 'fr', isArbitraryValue] }],\n            /**\n             * Grid Auto Rows\n             * @see https://tailwindcss.com/docs/grid-auto-rows\n             */\n            'auto-rows': [{ 'auto-rows': ['auto', 'min', 'max', 'fr', isArbitraryValue] }],\n            /**\n             * Gap\n             * @see https://tailwindcss.com/docs/gap\n             */\n            gap: [{ gap: [gap] }],\n            /**\n             * Gap X\n             * @see https://tailwindcss.com/docs/gap\n             */\n            'gap-x': [{ 'gap-x': [gap] }],\n            /**\n             * Gap Y\n             * @see https://tailwindcss.com/docs/gap\n             */\n            'gap-y': [{ 'gap-y': [gap] }],\n            /**\n             * Justify Content\n             * @see https://tailwindcss.com/docs/justify-content\n             */\n            'justify-content': [{ justify: getAlign() }],\n            /**\n             * Justify Items\n             * @see https://tailwindcss.com/docs/justify-items\n             */\n            'justify-items': [{ 'justify-items': ['start', 'end', 'center', 'stretch'] }],\n            /**\n             * Justify Self\n             * @see https://tailwindcss.com/docs/justify-self\n             */\n            'justify-self': [{ 'justify-self': ['auto', 'start', 'end', 'center', 'stretch'] }],\n            /**\n             * Align Content\n             * @see https://tailwindcss.com/docs/align-content\n             */\n            'align-content': [{ content: [...getAlign(), 'baseline'] }],\n            /**\n             * Align Items\n             * @see https://tailwindcss.com/docs/align-items\n             */\n            'align-items': [{ items: ['start', 'end', 'center', 'baseline', 'stretch'] }],\n            /**\n             * Align Self\n             * @see https://tailwindcss.com/docs/align-self\n             */\n            'align-self': [{ self: ['auto', 'start', 'end', 'center', 'stretch', 'baseline'] }],\n            /**\n             * Place Content\n             * @see https://tailwindcss.com/docs/place-content\n             */\n            'place-content': [{ 'place-content': [...getAlign(), 'baseline', 'stretch'] }],\n            /**\n             * Place Items\n             * @see https://tailwindcss.com/docs/place-items\n             */\n            'place-items': [{ 'place-items': ['start', 'end', 'center', 'baseline', 'stretch'] }],\n            /**\n             * Place Self\n             * @see https://tailwindcss.com/docs/place-self\n             */\n            'place-self': [{ 'place-self': ['auto', 'start', 'end', 'center', 'stretch'] }],\n            // Spacing\n            /**\n             * Padding\n             * @see https://tailwindcss.com/docs/padding\n             */\n            p: [{ p: [padding] }],\n            /**\n             * Padding X\n             * @see https://tailwindcss.com/docs/padding\n             */\n            px: [{ px: [padding] }],\n            /**\n             * Padding Y\n             * @see https://tailwindcss.com/docs/padding\n             */\n            py: [{ py: [padding] }],\n            /**\n             * Padding Top\n             * @see https://tailwindcss.com/docs/padding\n             */\n            pt: [{ pt: [padding] }],\n            /**\n             * Padding Right\n             * @see https://tailwindcss.com/docs/padding\n             */\n            pr: [{ pr: [padding] }],\n            /**\n             * Padding Bottom\n             * @see https://tailwindcss.com/docs/padding\n             */\n            pb: [{ pb: [padding] }],\n            /**\n             * Padding Left\n             * @see https://tailwindcss.com/docs/padding\n             */\n            pl: [{ pl: [padding] }],\n            /**\n             * Margin\n             * @see https://tailwindcss.com/docs/margin\n             */\n            m: [{ m: [margin] }],\n            /**\n             * Margin X\n             * @see https://tailwindcss.com/docs/margin\n             */\n            mx: [{ mx: [margin] }],\n            /**\n             * Margin Y\n             * @see https://tailwindcss.com/docs/margin\n             */\n            my: [{ my: [margin] }],\n            /**\n             * Margin Top\n             * @see https://tailwindcss.com/docs/margin\n             */\n            mt: [{ mt: [margin] }],\n            /**\n             * Margin Right\n             * @see https://tailwindcss.com/docs/margin\n             */\n            mr: [{ mr: [margin] }],\n            /**\n             * Margin Bottom\n             * @see https://tailwindcss.com/docs/margin\n             */\n            mb: [{ mb: [margin] }],\n            /**\n             * Margin Left\n             * @see https://tailwindcss.com/docs/margin\n             */\n            ml: [{ ml: [margin] }],\n            /**\n             * Space Between X\n             * @see https://tailwindcss.com/docs/space\n             */\n            'space-x': [{ 'space-x': [space] }],\n            /**\n             * Space Between X Reverse\n             * @see https://tailwindcss.com/docs/space\n             */\n            'space-x-reverse': ['space-x-reverse'],\n            /**\n             * Space Between Y\n             * @see https://tailwindcss.com/docs/space\n             */\n            'space-y': [{ 'space-y': [space] }],\n            /**\n             * Space Between Y Reverse\n             * @see https://tailwindcss.com/docs/space\n             */\n            'space-y-reverse': ['space-y-reverse'],\n            // Sizing\n            /**\n             * Width\n             * @see https://tailwindcss.com/docs/width\n             */\n            w: [{ w: ['auto', 'min', 'max', 'fit', spacing] }],\n            /**\n             * Min-Width\n             * @see https://tailwindcss.com/docs/min-width\n             */\n            'min-w': [{ 'min-w': ['min', 'max', 'fit', isLength] }],\n            /**\n             * Max-Width\n             * @see https://tailwindcss.com/docs/max-width\n             */\n            'max-w': [\n                {\n                    'max-w': [\n                        '0',\n                        'none',\n                        'full',\n                        'min',\n                        'max',\n                        'fit',\n                        'prose',\n                        { screen: [isTshirtSize] },\n                        isTshirtSize,\n                        isArbitraryLength,\n                    ],\n                },\n            ],\n            /**\n             * Height\n             * @see https://tailwindcss.com/docs/height\n             */\n            h: [{ h: [spacing, 'auto', 'min', 'max', 'fit'] }],\n            /**\n             * Min-Height\n             * @see https://tailwindcss.com/docs/min-height\n             */\n            'min-h': [{ 'min-h': ['min', 'max', 'fit', isLength] }],\n            /**\n             * Max-Height\n             * @see https://tailwindcss.com/docs/max-height\n             */\n            'max-h': [{ 'max-h': [spacing, 'min', 'max', 'fit'] }],\n            // Typography\n            /**\n             * Font Size\n             * @see https://tailwindcss.com/docs/font-size\n             */\n            'font-size': [{ text: ['base', isTshirtSize, isArbitraryLength] }],\n            /**\n             * Font Smoothing\n             * @see https://tailwindcss.com/docs/font-smoothing\n             */\n            'font-smoothing': ['antialiased', 'subpixel-antialiased'],\n            /**\n             * Font Style\n             * @see https://tailwindcss.com/docs/font-style\n             */\n            'font-style': ['italic', 'not-italic'],\n            /**\n             * Font Weight\n             * @see https://tailwindcss.com/docs/font-weight\n             */\n            'font-weight': [\n                {\n                    font: [\n                        'thin',\n                        'extralight',\n                        'light',\n                        'normal',\n                        'medium',\n                        'semibold',\n                        'bold',\n                        'extrabold',\n                        'black',\n                        isArbitraryNumber,\n                    ],\n                },\n            ],\n            /**\n             * Font Family\n             * @see https://tailwindcss.com/docs/font-family\n             */\n            'font-family': [{ font: [isAny] }],\n            /**\n             * Font Variant Numeric\n             * @see https://tailwindcss.com/docs/font-variant-numeric\n             */\n            'fvn-normal': ['normal-nums'],\n            /**\n             * Font Variant Numeric\n             * @see https://tailwindcss.com/docs/font-variant-numeric\n             */\n            'fvn-ordinal': ['ordinal'],\n            /**\n             * Font Variant Numeric\n             * @see https://tailwindcss.com/docs/font-variant-numeric\n             */\n            'fvn-slashed-zero': ['slashed-zero'],\n            /**\n             * Font Variant Numeric\n             * @see https://tailwindcss.com/docs/font-variant-numeric\n             */\n            'fvn-figure': ['lining-nums', 'oldstyle-nums'],\n            /**\n             * Font Variant Numeric\n             * @see https://tailwindcss.com/docs/font-variant-numeric\n             */\n            'fvn-spacing': ['proportional-nums', 'tabular-nums'],\n            /**\n             * Font Variant Numeric\n             * @see https://tailwindcss.com/docs/font-variant-numeric\n             */\n            'fvn-fraction': ['diagonal-fractions', 'stacked-fractons'],\n            /**\n             * Letter Spacing\n             * @see https://tailwindcss.com/docs/letter-spacing\n             */\n            tracking: [\n                {\n                    tracking: [\n                        'tighter',\n                        'tight',\n                        'normal',\n                        'wide',\n                        'wider',\n                        'widest',\n                        isArbitraryLength,\n                    ],\n                },\n            ],\n            /**\n             * Line Height\n             * @see https://tailwindcss.com/docs/line-height\n             */\n            leading: [\n                { leading: ['none', 'tight', 'snug', 'normal', 'relaxed', 'loose', isLength] },\n            ],\n            /**\n             * List Style Type\n             * @see https://tailwindcss.com/docs/list-style-type\n             */\n            'list-style-type': [{ list: ['none', 'disc', 'decimal', isArbitraryValue] }],\n            /**\n             * List Style Position\n             * @see https://tailwindcss.com/docs/list-style-position\n             */\n            'list-style-position': [{ list: ['inside', 'outside'] }],\n            /**\n             * Placeholder Color\n             * @deprecated since Tailwind CSS v3.0.0\n             * @see https://tailwindcss.com/docs/placeholder-color\n             */\n            'placeholder-color': [{ placeholder: [colors] }],\n            /**\n             * Placeholder Opacity\n             * @see https://tailwindcss.com/docs/placeholder-opacity\n             */\n            'placeholder-opacity': [{ 'placeholder-opacity': [opacity] }],\n            /**\n             * Text Alignment\n             * @see https://tailwindcss.com/docs/text-align\n             */\n            'text-alignment': [{ text: ['left', 'center', 'right', 'justify', 'start', 'end'] }],\n            /**\n             * Text Color\n             * @see https://tailwindcss.com/docs/text-color\n             */\n            'text-color': [{ text: [colors] }],\n            /**\n             * Text Opacity\n             * @see https://tailwindcss.com/docs/text-opacity\n             */\n            'text-opacity': [{ 'text-opacity': [opacity] }],\n            /**\n             * Text Decoration\n             * @see https://tailwindcss.com/docs/text-decoration\n             */\n            'text-decoration': ['underline', 'overline', 'line-through', 'no-underline'],\n            /**\n             * Text Decoration Style\n             * @see https://tailwindcss.com/docs/text-decoration-style\n             */\n            'text-decoration-style': [{ decoration: [...getLineStyles(), 'wavy'] }],\n            /**\n             * Text Decoration Thickness\n             * @see https://tailwindcss.com/docs/text-decoration-thickness\n             */\n            'text-decoration-thickness': [{ decoration: ['auto', 'from-font', isLength] }],\n            /**\n             * Text Underline Offset\n             * @see https://tailwindcss.com/docs/text-underline-offset\n             */\n            'underline-offset': [{ 'underline-offset': ['auto', isLength] }],\n            /**\n             * Text Decoration Color\n             * @see https://tailwindcss.com/docs/text-decoration-color\n             */\n            'text-decoration-color': [{ decoration: [colors] }],\n            /**\n             * Text Transform\n             * @see https://tailwindcss.com/docs/text-transform\n             */\n            'text-transform': ['uppercase', 'lowercase', 'capitalize', 'normal-case'],\n            /**\n             * Text Overflow\n             * @see https://tailwindcss.com/docs/text-overflow\n             */\n            'text-overflow': ['truncate', 'text-ellipsis', 'text-clip'],\n            /**\n             * Text Indent\n             * @see https://tailwindcss.com/docs/text-indent\n             */\n            indent: [{ indent: [spacing] }],\n            /**\n             * Vertical Alignment\n             * @see https://tailwindcss.com/docs/vertical-align\n             */\n            'vertical-align': [\n                {\n                    align: [\n                        'baseline',\n                        'top',\n                        'middle',\n                        'bottom',\n                        'text-top',\n                        'text-bottom',\n                        'sub',\n                        'super',\n                        isArbitraryLength,\n                    ],\n                },\n            ],\n            /**\n             * Whitespace\n             * @see https://tailwindcss.com/docs/whitespace\n             */\n            whitespace: [{ whitespace: ['normal', 'nowrap', 'pre', 'pre-line', 'pre-wrap'] }],\n            /**\n             * Word Break\n             * @see https://tailwindcss.com/docs/word-break\n             */\n            break: [{ break: ['normal', 'words', 'all', 'keep'] }],\n            /**\n             * Content\n             * @see https://tailwindcss.com/docs/content\n             */\n            content: [{ content: ['none', isArbitraryValue] }],\n            // Backgrounds\n            /**\n             * Background Attachment\n             * @see https://tailwindcss.com/docs/background-attachment\n             */\n            'bg-attachment': [{ bg: ['fixed', 'local', 'scroll'] }],\n            /**\n             * Background Clip\n             * @see https://tailwindcss.com/docs/background-clip\n             */\n            'bg-clip': [{ 'bg-clip': ['border', 'padding', 'content', 'text'] }],\n            /**\n             * Background Opacity\n             * @deprecated since Tailwind CSS v3.0.0\n             * @see https://tailwindcss.com/docs/background-opacity\n             */\n            'bg-opacity': [{ 'bg-opacity': [opacity] }],\n            /**\n             * Background Origin\n             * @see https://tailwindcss.com/docs/background-origin\n             */\n            'bg-origin': [{ 'bg-origin': ['border', 'padding', 'content'] }],\n            /**\n             * Background Position\n             * @see https://tailwindcss.com/docs/background-position\n             */\n            'bg-position': [{ bg: [...getPositions(), isArbitraryPosition] }],\n            /**\n             * Background Repeat\n             * @see https://tailwindcss.com/docs/background-repeat\n             */\n            'bg-repeat': [{ bg: ['no-repeat', { repeat: ['', 'x', 'y', 'round', 'space'] }] }],\n            /**\n             * Background Size\n             * @see https://tailwindcss.com/docs/background-size\n             */\n            'bg-size': [{ bg: ['auto', 'cover', 'contain', isArbitrarySize] }],\n            /**\n             * Background Image\n             * @see https://tailwindcss.com/docs/background-image\n             */\n            'bg-image': [\n                {\n                    bg: [\n                        'none',\n                        { 'gradient-to': ['t', 'tr', 'r', 'br', 'b', 'bl', 'l', 'tl'] },\n                        isArbitraryUrl,\n                    ],\n                },\n            ],\n            /**\n             * Background Color\n             * @see https://tailwindcss.com/docs/background-color\n             */\n            'bg-color': [{ bg: [colors] }],\n            /**\n             * Gradient Color Stops From\n             * @see https://tailwindcss.com/docs/gradient-color-stops\n             */\n            'gradient-from': [{ from: [gradientColorStops] }],\n            /**\n             * Gradient Color Stops Via\n             * @see https://tailwindcss.com/docs/gradient-color-stops\n             */\n            'gradient-via': [{ via: [gradientColorStops] }],\n            /**\n             * Gradient Color Stops To\n             * @see https://tailwindcss.com/docs/gradient-color-stops\n             */\n            'gradient-to': [{ to: [gradientColorStops] }],\n            // Borders\n            /**\n             * Border Radius\n             * @see https://tailwindcss.com/docs/border-radius\n             */\n            rounded: [{ rounded: [borderRadius] }],\n            /**\n             * Border Radius Top\n             * @see https://tailwindcss.com/docs/border-radius\n             */\n            'rounded-t': [{ 'rounded-t': [borderRadius] }],\n            /**\n             * Border Radius Right\n             * @see https://tailwindcss.com/docs/border-radius\n             */\n            'rounded-r': [{ 'rounded-r': [borderRadius] }],\n            /**\n             * Border Radius Bottom\n             * @see https://tailwindcss.com/docs/border-radius\n             */\n            'rounded-b': [{ 'rounded-b': [borderRadius] }],\n            /**\n             * Border Radius Left\n             * @see https://tailwindcss.com/docs/border-radius\n             */\n            'rounded-l': [{ 'rounded-l': [borderRadius] }],\n            /**\n             * Border Radius Top Left\n             * @see https://tailwindcss.com/docs/border-radius\n             */\n            'rounded-tl': [{ 'rounded-tl': [borderRadius] }],\n            /**\n             * Border Radius Top Right\n             * @see https://tailwindcss.com/docs/border-radius\n             */\n            'rounded-tr': [{ 'rounded-tr': [borderRadius] }],\n            /**\n             * Border Radius Bottom Right\n             * @see https://tailwindcss.com/docs/border-radius\n             */\n            'rounded-br': [{ 'rounded-br': [borderRadius] }],\n            /**\n             * Border Radius Bottom Left\n             * @see https://tailwindcss.com/docs/border-radius\n             */\n            'rounded-bl': [{ 'rounded-bl': [borderRadius] }],\n            /**\n             * Border Width\n             * @see https://tailwindcss.com/docs/border-width\n             */\n            'border-w': [{ border: [borderWidth] }],\n            /**\n             * Border Width X\n             * @see https://tailwindcss.com/docs/border-width\n             */\n            'border-w-x': [{ 'border-x': [borderWidth] }],\n            /**\n             * Border Width Y\n             * @see https://tailwindcss.com/docs/border-width\n             */\n            'border-w-y': [{ 'border-y': [borderWidth] }],\n            /**\n             * Border Width Top\n             * @see https://tailwindcss.com/docs/border-width\n             */\n            'border-w-t': [{ 'border-t': [borderWidth] }],\n            /**\n             * Border Width Right\n             * @see https://tailwindcss.com/docs/border-width\n             */\n            'border-w-r': [{ 'border-r': [borderWidth] }],\n            /**\n             * Border Width Bottom\n             * @see https://tailwindcss.com/docs/border-width\n             */\n            'border-w-b': [{ 'border-b': [borderWidth] }],\n            /**\n             * Border Width Left\n             * @see https://tailwindcss.com/docs/border-width\n             */\n            'border-w-l': [{ 'border-l': [borderWidth] }],\n            /**\n             * Border Opacity\n             * @see https://tailwindcss.com/docs/border-opacity\n             */\n            'border-opacity': [{ 'border-opacity': [opacity] }],\n            /**\n             * Border Style\n             * @see https://tailwindcss.com/docs/border-style\n             */\n            'border-style': [{ border: [...getLineStyles(), 'hidden'] }],\n            /**\n             * Divide Width X\n             * @see https://tailwindcss.com/docs/divide-width\n             */\n            'divide-x': [{ 'divide-x': [borderWidth] }],\n            /**\n             * Divide Width X Reverse\n             * @see https://tailwindcss.com/docs/divide-width\n             */\n            'divide-x-reverse': ['divide-x-reverse'],\n            /**\n             * Divide Width Y\n             * @see https://tailwindcss.com/docs/divide-width\n             */\n            'divide-y': [{ 'divide-y': [borderWidth] }],\n            /**\n             * Divide Width Y Reverse\n             * @see https://tailwindcss.com/docs/divide-width\n             */\n            'divide-y-reverse': ['divide-y-reverse'],\n            /**\n             * Divide Opacity\n             * @see https://tailwindcss.com/docs/divide-opacity\n             */\n            'divide-opacity': [{ 'divide-opacity': [opacity] }],\n            /**\n             * Divide Style\n             * @see https://tailwindcss.com/docs/divide-style\n             */\n            'divide-style': [{ divide: getLineStyles() }],\n            /**\n             * Border Color\n             * @see https://tailwindcss.com/docs/border-color\n             */\n            'border-color': [{ border: [borderColor] }],\n            /**\n             * Border Color X\n             * @see https://tailwindcss.com/docs/border-color\n             */\n            'border-color-x': [{ 'border-x': [borderColor] }],\n            /**\n             * Border Color Y\n             * @see https://tailwindcss.com/docs/border-color\n             */\n            'border-color-y': [{ 'border-y': [borderColor] }],\n            /**\n             * Border Color Top\n             * @see https://tailwindcss.com/docs/border-color\n             */\n            'border-color-t': [{ 'border-t': [borderColor] }],\n            /**\n             * Border Color Right\n             * @see https://tailwindcss.com/docs/border-color\n             */\n            'border-color-r': [{ 'border-r': [borderColor] }],\n            /**\n             * Border Color Bottom\n             * @see https://tailwindcss.com/docs/border-color\n             */\n            'border-color-b': [{ 'border-b': [borderColor] }],\n            /**\n             * Border Color Left\n             * @see https://tailwindcss.com/docs/border-color\n             */\n            'border-color-l': [{ 'border-l': [borderColor] }],\n            /**\n             * Divide Color\n             * @see https://tailwindcss.com/docs/divide-color\n             */\n            'divide-color': [{ divide: [borderColor] }],\n            /**\n             * Outline Style\n             * @see https://tailwindcss.com/docs/outline-style\n             */\n            'outline-style': [{ outline: ['', ...getLineStyles()] }],\n            /**\n             * Outline Offset\n             * @see https://tailwindcss.com/docs/outline-offset\n             */\n            'outline-offset': [{ 'outline-offset': [isLength] }],\n            /**\n             * Outline Width\n             * @see https://tailwindcss.com/docs/outline-width\n             */\n            'outline-w': [{ outline: [isLength] }],\n            /**\n             * Outline Color\n             * @see https://tailwindcss.com/docs/outline-color\n             */\n            'outline-color': [{ outline: [colors] }],\n            /**\n             * Ring Width\n             * @see https://tailwindcss.com/docs/ring-width\n             */\n            'ring-w': [{ ring: getLengthWithEmpty() }],\n            /**\n             * Ring Width Inset\n             * @see https://tailwindcss.com/docs/ring-width\n             */\n            'ring-w-inset': ['ring-inset'],\n            /**\n             * Ring Color\n             * @see https://tailwindcss.com/docs/ring-color\n             */\n            'ring-color': [{ ring: [colors] }],\n            /**\n             * Ring Opacity\n             * @see https://tailwindcss.com/docs/ring-opacity\n             */\n            'ring-opacity': [{ 'ring-opacity': [opacity] }],\n            /**\n             * Ring Offset Width\n             * @see https://tailwindcss.com/docs/ring-offset-width\n             */\n            'ring-offset-w': [{ 'ring-offset': [isLength] }],\n            /**\n             * Ring Offset Color\n             * @see https://tailwindcss.com/docs/ring-offset-color\n             */\n            'ring-offset-color': [{ 'ring-offset': [colors] }],\n            // Effects\n            /**\n             * Box Shadow\n             * @see https://tailwindcss.com/docs/box-shadow\n             */\n            shadow: [{ shadow: ['', 'inner', 'none', isTshirtSize, isArbitraryShadow] }],\n            /**\n             * Box Shadow Color\n             * @see https://tailwindcss.com/docs/box-shadow-color\n             */\n            'shadow-color': [{ shadow: [isAny] }],\n            /**\n             * Opacity\n             * @see https://tailwindcss.com/docs/opacity\n             */\n            opacity: [{ opacity: [opacity] }],\n            /**\n             * Mix Beldn Mode\n             * @see https://tailwindcss.com/docs/mix-blend-mode\n             */\n            'mix-blend': [{ 'mix-blend': getBlendModes() }],\n            /**\n             * Background Blend Mode\n             * @see https://tailwindcss.com/docs/background-blend-mode\n             */\n            'bg-blend': [{ 'bg-blend': getBlendModes() }],\n            // Filters\n            /**\n             * Filter\n             * @deprecated since Tailwind CSS v3.0.0\n             * @see https://tailwindcss.com/docs/filter\n             */\n            filter: [{ filter: ['', 'none'] }],\n            /**\n             * Blur\n             * @see https://tailwindcss.com/docs/blur\n             */\n            blur: [{ blur: [blur] }],\n            /**\n             * Brightness\n             * @see https://tailwindcss.com/docs/brightness\n             */\n            brightness: [{ brightness: [brightness] }],\n            /**\n             * Contrast\n             * @see https://tailwindcss.com/docs/contrast\n             */\n            contrast: [{ contrast: [contrast] }],\n            /**\n             * Drop Shadow\n             * @see https://tailwindcss.com/docs/drop-shadow\n             */\n            'drop-shadow': [{ 'drop-shadow': ['', 'none', isTshirtSize, isArbitraryValue] }],\n            /**\n             * Grayscale\n             * @see https://tailwindcss.com/docs/grayscale\n             */\n            grayscale: [{ grayscale: [grayscale] }],\n            /**\n             * Hue Rotate\n             * @see https://tailwindcss.com/docs/hue-rotate\n             */\n            'hue-rotate': [{ 'hue-rotate': [hueRotate] }],\n            /**\n             * Invert\n             * @see https://tailwindcss.com/docs/invert\n             */\n            invert: [{ invert: [invert] }],\n            /**\n             * Saturate\n             * @see https://tailwindcss.com/docs/saturate\n             */\n            saturate: [{ saturate: [saturate] }],\n            /**\n             * Sepia\n             * @see https://tailwindcss.com/docs/sepia\n             */\n            sepia: [{ sepia: [sepia] }],\n            /**\n             * Backdrop Filter\n             * @deprecated since Tailwind CSS v3.0.0\n             * @see https://tailwindcss.com/docs/backdrop-filter\n             */\n            'backdrop-filter': [{ 'backdrop-filter': ['', 'none'] }],\n            /**\n             * Backdrop Blur\n             * @see https://tailwindcss.com/docs/backdrop-blur\n             */\n            'backdrop-blur': [{ 'backdrop-blur': [blur] }],\n            /**\n             * Backdrop Brightness\n             * @see https://tailwindcss.com/docs/backdrop-brightness\n             */\n            'backdrop-brightness': [{ 'backdrop-brightness': [brightness] }],\n            /**\n             * Backdrop Contrast\n             * @see https://tailwindcss.com/docs/backdrop-contrast\n             */\n            'backdrop-contrast': [{ 'backdrop-contrast': [contrast] }],\n            /**\n             * Backdrop Grayscale\n             * @see https://tailwindcss.com/docs/backdrop-grayscale\n             */\n            'backdrop-grayscale': [{ 'backdrop-grayscale': [grayscale] }],\n            /**\n             * Backdrop Hue Rotate\n             * @see https://tailwindcss.com/docs/backdrop-hue-rotate\n             */\n            'backdrop-hue-rotate': [{ 'backdrop-hue-rotate': [hueRotate] }],\n            /**\n             * Backdrop Invert\n             * @see https://tailwindcss.com/docs/backdrop-invert\n             */\n            'backdrop-invert': [{ 'backdrop-invert': [invert] }],\n            /**\n             * Backdrop Opacity\n             * @see https://tailwindcss.com/docs/backdrop-opacity\n             */\n            'backdrop-opacity': [{ 'backdrop-opacity': [opacity] }],\n            /**\n             * Backdrop Saturate\n             * @see https://tailwindcss.com/docs/backdrop-saturate\n             */\n            'backdrop-saturate': [{ 'backdrop-saturate': [saturate] }],\n            /**\n             * Backdrop Sepia\n             * @see https://tailwindcss.com/docs/backdrop-sepia\n             */\n            'backdrop-sepia': [{ 'backdrop-sepia': [sepia] }],\n            // Tables\n            /**\n             * Border Collapse\n             * @see https://tailwindcss.com/docs/border-collapse\n             */\n            'border-collapse': [{ border: ['collapse', 'separate'] }],\n            /**\n             * Border Spacing\n             * @see https://tailwindcss.com/docs/border-spacing\n             */\n            'border-spacing': [{ 'border-spacing': [borderSpacing] }],\n            /**\n             * Border Spacing X\n             * @see https://tailwindcss.com/docs/border-spacing\n             */\n            'border-spacing-x': [{ 'border-spacing-x': [borderSpacing] }],\n            /**\n             * Border Spacing Y\n             * @see https://tailwindcss.com/docs/border-spacing\n             */\n            'border-spacing-y': [{ 'border-spacing-y': [borderSpacing] }],\n            /**\n             * Table Layout\n             * @see https://tailwindcss.com/docs/table-layout\n             */\n            'table-layout': [{ table: ['auto', 'fixed'] }],\n            // Transitions and Animation\n            /**\n             * Tranisition Property\n             * @see https://tailwindcss.com/docs/transition-property\n             */\n            transition: [\n                {\n                    transition: [\n                        'none',\n                        'all',\n                        '',\n                        'colors',\n                        'opacity',\n                        'shadow',\n                        'transform',\n                        isArbitraryValue,\n                    ],\n                },\n            ],\n            /**\n             * Transition Duration\n             * @see https://tailwindcss.com/docs/transition-duration\n             */\n            duration: [{ duration: getNumberAndArbitrary() }],\n            /**\n             * Transition Timing Function\n             * @see https://tailwindcss.com/docs/transition-timing-function\n             */\n            ease: [{ ease: ['linear', 'in', 'out', 'in-out', isArbitraryValue] }],\n            /**\n             * Transition Delay\n             * @see https://tailwindcss.com/docs/transition-delay\n             */\n            delay: [{ delay: getNumberAndArbitrary() }],\n            /**\n             * Animation\n             * @see https://tailwindcss.com/docs/animation\n             */\n            animate: [{ animate: ['none', 'spin', 'ping', 'pulse', 'bounce', isArbitraryValue] }],\n            // Transforms\n            /**\n             * Transform\n             * @see https://tailwindcss.com/docs/transform\n             */\n            transform: [{ transform: ['', 'gpu', 'none'] }],\n            /**\n             * Scale\n             * @see https://tailwindcss.com/docs/scale\n             */\n            scale: [{ scale: [scale] }],\n            /**\n             * Scale X\n             * @see https://tailwindcss.com/docs/scale\n             */\n            'scale-x': [{ 'scale-x': [scale] }],\n            /**\n             * Scale Y\n             * @see https://tailwindcss.com/docs/scale\n             */\n            'scale-y': [{ 'scale-y': [scale] }],\n            /**\n             * Rotate\n             * @see https://tailwindcss.com/docs/rotate\n             */\n            rotate: [{ rotate: [isInteger, isArbitraryValue] }],\n            /**\n             * Translate X\n             * @see https://tailwindcss.com/docs/translate\n             */\n            'translate-x': [{ 'translate-x': [translate] }],\n            /**\n             * Translate Y\n             * @see https://tailwindcss.com/docs/translate\n             */\n            'translate-y': [{ 'translate-y': [translate] }],\n            /**\n             * Skew X\n             * @see https://tailwindcss.com/docs/skew\n             */\n            'skew-x': [{ 'skew-x': [skew] }],\n            /**\n             * Skew Y\n             * @see https://tailwindcss.com/docs/skew\n             */\n            'skew-y': [{ 'skew-y': [skew] }],\n            /**\n             * Transform Origin\n             * @see https://tailwindcss.com/docs/transform-origin\n             */\n            'transform-origin': [\n                {\n                    origin: [\n                        'center',\n                        'top',\n                        'top-right',\n                        'right',\n                        'bottom-right',\n                        'bottom',\n                        'bottom-left',\n                        'left',\n                        'top-left',\n                        isArbitraryValue,\n                    ],\n                },\n            ],\n            // Interactivity\n            /**\n             * Accent Color\n             * @see https://tailwindcss.com/docs/accent-color\n             */\n            accent: [{ accent: ['auto', colors] }],\n            /**\n             * Appearance\n             * @see https://tailwindcss.com/docs/appearance\n             */\n            appearance: ['appearance-none'],\n            /**\n             * Cursor\n             * @see https://tailwindcss.com/docs/cursor\n             */\n            cursor: [\n                {\n                    cursor: [\n                        'auto',\n                        'default',\n                        'pointer',\n                        'wait',\n                        'text',\n                        'move',\n                        'help',\n                        'not-allowed',\n                        'none',\n                        'context-menu',\n                        'progress',\n                        'cell',\n                        'crosshair',\n                        'vertical-text',\n                        'alias',\n                        'copy',\n                        'no-drop',\n                        'grab',\n                        'grabbing',\n                        'all-scroll',\n                        'col-resize',\n                        'row-resize',\n                        'n-resize',\n                        'e-resize',\n                        's-resize',\n                        'w-resize',\n                        'ne-resize',\n                        'nw-resize',\n                        'se-resize',\n                        'sw-resize',\n                        'ew-resize',\n                        'ns-resize',\n                        'nesw-resize',\n                        'nwse-resize',\n                        'zoom-in',\n                        'zoom-out',\n                        isArbitraryValue,\n                    ],\n                },\n            ],\n            /**\n             * Caret Color\n             * @see https://tailwindcss.com/docs/just-in-time-mode#caret-color-utilities\n             */\n            'caret-color': [{ caret: [colors] }],\n            /**\n             * Pointer Events\n             * @see https://tailwindcss.com/docs/pointer-events\n             */\n            'pointer-events': [{ 'pointer-events': ['none', 'auto'] }],\n            /**\n             * Resize\n             * @see https://tailwindcss.com/docs/resize\n             */\n            resize: [{ resize: ['none', 'y', 'x', ''] }],\n            /**\n             * Scroll Behavior\n             * @see https://tailwindcss.com/docs/scroll-behavior\n             */\n            'scroll-behavior': [{ scroll: ['auto', 'smooth'] }],\n            /**\n             * Scroll Margin\n             * @see https://tailwindcss.com/docs/scroll-margin\n             */\n            'scroll-m': [{ 'scroll-m': [spacing] }],\n            /**\n             * Scroll Margin X\n             * @see https://tailwindcss.com/docs/scroll-margin\n             */\n            'scroll-mx': [{ 'scroll-mx': [spacing] }],\n            /**\n             * Scroll Margin Y\n             * @see https://tailwindcss.com/docs/scroll-margin\n             */\n            'scroll-my': [{ 'scroll-my': [spacing] }],\n            /**\n             * Scroll Margin Top\n             * @see https://tailwindcss.com/docs/scroll-margin\n             */\n            'scroll-mt': [{ 'scroll-mt': [spacing] }],\n            /**\n             * Scroll Margin Right\n             * @see https://tailwindcss.com/docs/scroll-margin\n             */\n            'scroll-mr': [{ 'scroll-mr': [spacing] }],\n            /**\n             * Scroll Margin Bottom\n             * @see https://tailwindcss.com/docs/scroll-margin\n             */\n            'scroll-mb': [{ 'scroll-mb': [spacing] }],\n            /**\n             * Scroll Margin Left\n             * @see https://tailwindcss.com/docs/scroll-margin\n             */\n            'scroll-ml': [{ 'scroll-ml': [spacing] }],\n            /**\n             * Scroll Padding\n             * @see https://tailwindcss.com/docs/scroll-padding\n             */\n            'scroll-p': [{ 'scroll-p': [spacing] }],\n            /**\n             * Scroll Padding X\n             * @see https://tailwindcss.com/docs/scroll-padding\n             */\n            'scroll-px': [{ 'scroll-px': [spacing] }],\n            /**\n             * Scroll Padding Y\n             * @see https://tailwindcss.com/docs/scroll-padding\n             */\n            'scroll-py': [{ 'scroll-py': [spacing] }],\n            /**\n             * Scroll Padding Top\n             * @see https://tailwindcss.com/docs/scroll-padding\n             */\n            'scroll-pt': [{ 'scroll-pt': [spacing] }],\n            /**\n             * Scroll Padding Right\n             * @see https://tailwindcss.com/docs/scroll-padding\n             */\n            'scroll-pr': [{ 'scroll-pr': [spacing] }],\n            /**\n             * Scroll Padding Bottom\n             * @see https://tailwindcss.com/docs/scroll-padding\n             */\n            'scroll-pb': [{ 'scroll-pb': [spacing] }],\n            /**\n             * Scroll Padding Left\n             * @see https://tailwindcss.com/docs/scroll-padding\n             */\n            'scroll-pl': [{ 'scroll-pl': [spacing] }],\n            /**\n             * Scroll Snap Align\n             * @see https://tailwindcss.com/docs/scroll-snap-align\n             */\n            'snap-align': [{ snap: ['start', 'end', 'center', 'align-none'] }],\n            /**\n             * Scroll Snap Stop\n             * @see https://tailwindcss.com/docs/scroll-snap-stop\n             */\n            'snap-stop': [{ snap: ['normal', 'always'] }],\n            /**\n             * Scroll Snap Type\n             * @see https://tailwindcss.com/docs/scroll-snap-type\n             */\n            'snap-type': [{ snap: ['none', 'x', 'y', 'both'] }],\n            /**\n             * Scroll Snap Type Strictness\n             * @see https://tailwindcss.com/docs/scroll-snap-type\n             */\n            'snap-strictness': [{ snap: ['mandatory', 'proximity'] }],\n            /**\n             * Touch Action\n             * @see https://tailwindcss.com/docs/touch-action\n             */\n            touch: [\n                {\n                    touch: [\n                        'auto',\n                        'none',\n                        'pinch-zoom',\n                        'manipulation',\n                        { pan: ['x', 'left', 'right', 'y', 'up', 'down'] },\n                    ],\n                },\n            ],\n            /**\n             * User Select\n             * @see https://tailwindcss.com/docs/user-select\n             */\n            select: [{ select: ['none', 'text', 'all', 'auto'] }],\n            /**\n             * Will Change\n             * @see https://tailwindcss.com/docs/will-change\n             */\n            'will-change': [\n                { 'will-change': ['auto', 'scroll', 'contents', 'transform', isArbitraryValue] },\n            ],\n            // SVG\n            /**\n             * Fill\n             * @see https://tailwindcss.com/docs/fill\n             */\n            fill: [{ fill: [colors, 'none'] }],\n            /**\n             * Stroke Width\n             * @see https://tailwindcss.com/docs/stroke-width\n             */\n            'stroke-w': [{ stroke: [isLength, isArbitraryNumber] }],\n            /**\n             * Stroke\n             * @see https://tailwindcss.com/docs/stroke\n             */\n            stroke: [{ stroke: [colors, 'none'] }],\n            // Accessibility\n            /**\n             * Screen Readers\n             * @see https://tailwindcss.com/docs/screen-readers\n             */\n            sr: ['sr-only', 'not-sr-only'],\n        },\n        conflictingClassGroups: {\n            overflow: ['overflow-x', 'overflow-y'],\n            overscroll: ['overscroll-x', 'overscroll-y'],\n            inset: ['inset-x', 'inset-y', 'top', 'right', 'bottom', 'left'],\n            'inset-x': ['right', 'left'],\n            'inset-y': ['top', 'bottom'],\n            flex: ['basis', 'grow', 'shrink'],\n            gap: ['gap-x', 'gap-y'],\n            p: ['px', 'py', 'pt', 'pr', 'pb', 'pl'],\n            px: ['pr', 'pl'],\n            py: ['pt', 'pb'],\n            m: ['mx', 'my', 'mt', 'mr', 'mb', 'ml'],\n            mx: ['mr', 'ml'],\n            my: ['mt', 'mb'],\n            'font-size': ['leading'],\n            'fvn-normal': [\n                'fvn-ordinal',\n                'fvn-slashed-zero',\n                'fvn-figure',\n                'fvn-spacing',\n                'fvn-fraction',\n            ],\n            'fvn-ordinal': ['fvn-normal'],\n            'fvn-slashed-zero': ['fvn-normal'],\n            'fvn-figure': ['fvn-normal'],\n            'fvn-spacing': ['fvn-normal'],\n            'fvn-fraction': ['fvn-normal'],\n            rounded: [\n                'rounded-t',\n                'rounded-r',\n                'rounded-b',\n                'rounded-l',\n                'rounded-tl',\n                'rounded-tr',\n                'rounded-br',\n                'rounded-bl',\n            ],\n            'rounded-t': ['rounded-tl', 'rounded-tr'],\n            'rounded-r': ['rounded-tr', 'rounded-br'],\n            'rounded-b': ['rounded-br', 'rounded-bl'],\n            'rounded-l': ['rounded-tl', 'rounded-bl'],\n            'border-spacing': ['border-spacing-x', 'border-spacing-y'],\n            'border-w': ['border-w-t', 'border-w-r', 'border-w-b', 'border-w-l'],\n            'border-w-x': ['border-w-r', 'border-w-l'],\n            'border-w-y': ['border-w-t', 'border-w-b'],\n            'border-color': [\n                'border-color-t',\n                'border-color-r',\n                'border-color-b',\n                'border-color-l',\n            ],\n            'border-color-x': ['border-color-r', 'border-color-l'],\n            'border-color-y': ['border-color-t', 'border-color-b'],\n            'scroll-m': [\n                'scroll-mx',\n                'scroll-my',\n                'scroll-mt',\n                'scroll-mr',\n                'scroll-mb',\n                'scroll-ml',\n            ],\n            'scroll-mx': ['scroll-mr', 'scroll-ml'],\n            'scroll-my': ['scroll-mt', 'scroll-mb'],\n            'scroll-p': [\n                'scroll-px',\n                'scroll-py',\n                'scroll-pt',\n                'scroll-pr',\n                'scroll-pb',\n                'scroll-pl',\n            ],\n            'scroll-px': ['scroll-pr', 'scroll-pl'],\n            'scroll-py': ['scroll-pt', 'scroll-pb'],\n        },\n    } as const\n}\n", "import { createTailwindMerge } from './create-tailwind-merge'\nimport { getDefaultConfig } from './default-config'\n\nexport const twMerge = createTailwindMerge(getDefaultConfig)\n", "// We import the CSS which is extracted to its own file by esbuild.\nimport persist from '@alpinejs/persist'\nimport Splide from '@splidejs/splide'\nimport Alpine from 'alpinejs'\nimport { format as formatDate, parseISO as parseDate } from 'date-fns'\nimport { Socket } from 'phoenix'\nimport 'phoenix_html'\nimport { LiveSocket } from 'phoenix_live_view'\nimport { twMerge } from 'tailwind-merge'\nimport { screens } from 'tailwindcss/defaultTheme'\nimport Account from './account.js'\nimport {\n  clipboard,\n  formatDuration,\n  formatMoney,\n  formatPercent,\n  timeToNextWeeklyReset,\n} from './common.js'\nimport emailForm from './email_form'\nimport Onboarding from './onboarding.js'\nimport VimeoPlayer from './player.js'\nimport Plyr from './plyr.js'\nimport Project from './project.js'\nimport QuestHandler from './quest_handler.js'\nimport Sharing from './sharing.js'\nimport { Sortable } from \"./sortable_list\";\nimport Swiper from './swiper.js'\nimport { sparks, timer, toast, vh100 } from './util.js'\nimport FlipList from './hooks/flip_list.js'\nimport creditsRoll from './hooks/credits_sync.js'\nimport RankPreview from './hooks/rank_preview.js'\nimport PXCountdown from './hooks/px_countdown.js'\nimport PopcornHooks from './hooks/popcorn.js'\nimport initLandingFill from './landing/fill.js'\nimport sleepWhenIdle from './idle_sleep.js'\nimport sjPage from './shows_j.js'\nimport lootSheet from './loot_sheet.js'\nimport joinSheet from './join_sheet.js'\nimport {\n  installSubCounters,\n  keepRangeValue,\n  pxHeaderBalance,\n  pxLadder,\n  pxModalDragGuard,\n  pxRoll,\n  pxShare,\n  pxSlider,\n  pxTip,\n  pxTour,\n} from './project_x.js'\n\ninstallSubCounters()\n\nimport { installClickyGoals } from './clicky_goals.js'\nimport { installAdEvents } from './ad_events.js'\n\ninstallClickyGoals()\ninstallAdEvents()\n\nimport '@mux/mux-player'\n\nlet Hooks = {\n  PushFragment: {\n    mounted() {\n      this.pushEvent('fragment-mounted', { fragment: window.location.hash })\n    },\n  },\n  IframeResize: {\n    mounted() {\n      this.el.style.height =\n        this.el.contentWindow.document.body.scrollHeight + 'px'\n    },\n    updated() {\n      this.el.style.height =\n        this.el.contentWindow.document.body.scrollHeight + 'px'\n    },\n  },\n  Sortable,\n  FlipList,\n  RankPreview,\n  PXCountdown,\n  ...PopcornHooks,\n}\n\nlet csrfToken = document\n  .querySelector(\"meta[name='csrf-token']\")\n  .getAttribute('content')\n\n\n\nlet liveSocket = new LiveSocket('/live', Socket, {\n  params: { _csrf_token: csrfToken },\n  hooks: Hooks,\n  dom: {\n    onBeforeElUpdated(from, to) {\n      if (from._x_dataStack) {\n        window.Alpine.clone(from, to)\n      }\n      keepRangeValue(from, to)\n    },\n  },\n})\nwindow.emailForm = emailForm\n\nliveSocket.connect()\nwindow.liveSocket = liveSocket\n// /show and /x tabs nobody is looking at let go of their connection.\nwindow.liveSleep = sleepWhenIdle(liveSocket)\n\n// Landing page (landing.v4, \"The Fill\"). No-ops elsewhere.\ninitLandingFill()\n\n// Claim, Log in and Buy LOOT come back to this page (data-return-here: the\n// address the page was served at). /shows moves its address without a\n// reload (?show=<slug> once a show is picked), so send where the page is\n// now; the server drops anything it shouldn't keep (LocalPath). A return_to\n// that something else has set since (a sheet's own way back) is left as it is.\ndocument.addEventListener(\n  'submit',\n  (e) => {\n    for (const input of e.target.querySelectorAll('input[data-return-here]')) {\n      if (input.value === input.dataset.returnHere) input.value = location.pathname + location.search\n    }\n  },\n  true\n)\n\nAlpine.plugin(persist)\n\nwindow.Alpine = Alpine\n\nconst mediumBreakpoint = screens.md.slice(0, -2)\nconst largeBreakpoint = screens.lg.slice(0, -2)\n\nif (document.querySelector('.splide')) {\n  let elms = document.getElementsByClassName('splide')\n\n  let splideOptions = {\n    type: 'slide',\n    /* gaps and padding here are to match the max-width wrapper */\n    gap: '1.5rem',\n    padding: '1.5rem',\n    pagination: false,\n    autoWidth: true,\n    mediaQuery: 'min',\n    drag: 'free',\n    snap: false,\n    arrows: false,\n    wheel: true,\n    waitForTransition: true,\n    releaseWheel: true,\n    breakpoints: {\n      [mediumBreakpoint]: {\n        arrows: true,\n        padding: '3rem',\n        gap: '3rem',\n      },\n    },\n  }\n\n  for (let i = 0; i < elms.length; i++) {\n    new Splide(elms[i], splideOptions).mount()\n  }\n\n  // var splide = new Splide('.splide',\n  // splide.mount()\n}\n\nAlpine.data('project', Project)\nAlpine.data('timer', timer)\nAlpine.data('toast', toast)\nAlpine.data('onboarding', Onboarding)\nAlpine.data('account', Account)\nAlpine.data('questHandler', QuestHandler)\nAlpine.data('share', Sharing)\n\nAlpine.data('sparks', sparks)\nAlpine.data('vh100', vh100)\n\npxModalDragGuard()\nAlpine.data('pxSlider', pxSlider)\nAlpine.data('pxLadder', pxLadder)\nAlpine.data('pxRoll', pxRoll)\nAlpine.data('pxShare', pxShare)\nAlpine.data('pxHeaderBalance', pxHeaderBalance)\nAlpine.data('pxTip', pxTip)\nAlpine.data('pxTour', pxTour)\nAlpine.data('plyr', Plyr)\nAlpine.data('player', VimeoPlayer)\nAlpine.data('creditsRoll', creditsRoll)\nAlpine.data('swiper', Swiper)\nAlpine.data('sjPage', sjPage)\nAlpine.data('lootSheet', lootSheet)\nAlpine.data('joinSheet', joinSheet)\n\n// Global - Magic Functions\nAlpine.magic('clipboard', clipboard)\nAlpine.magic('formatMoney', formatMoney)\nAlpine.magic('formatPercent', formatPercent)\nAlpine.magic('formatDuration', formatDuration)\nAlpine.magic('timeToNextWeeklyReset', timeToNextWeeklyReset)\nAlpine.magic(\n  'formatDate',\n  () =>\n    (date, format = 'LL/dd/yyyy') =>\n      formatDate(parseDate(date), format)\n)\nAlpine.magic(\n  'twMerge',\n  () =>\n    (...args) =>\n      twMerge(...args)\n)\nAlpine.magic(\n  'cn',\n  () =>\n    (...args) =>\n      args.filter(Boolean).join(' ')\n)\n\nAlpine.magic('scroll', () => (el) => {\n  const element = document.querySelector(el)\n  element?.scrollIntoView({ behavior: 'smooth' })\n})\n\nAlpine.start()\n\n// DISABLE DATA DOG FOR NOW\n// const user_id = document.querySelector('meta[name=\"loortv:user_id\"]')?.content\n// if (process.env.NODE_ENV === 'production') {\n//   datadogRum.init({\n//     applicationId: 'c5936bda-d92b-449e-af93-22ab1c7d1fa2',\n//     clientToken: 'pubc0449dbe8b795cdb00f4aeaca6010f84',\n//     site: 'us5.datadoghq.com',\n//     service: 'loor.tv',\n//     env: 'prod',\n//     // Specify a version number to identify the deployed version of your application in Datadog\n//     // version: '1.0.0',\n//     sessionSampleRate: 100,\n//     premiumSampleRate: 100,\n//     trackUserInteractions: true,\n//     defaultPrivacyLevel: 'mask-user-input',\n//   })\n\n//   if (user_id) {\n//     datadogRum.setUser({ id: user_id })\n//   } else {\n//     datadogRum.setUser({ id: 'anon' })\n//   }\n//   datadogRum.startSessionReplayRecording()\n// } else {\n//   console.log(`Datadog RUM not enabled in development: user_id: ${user_id}`)\n// }\n\n// Reduce Honeybadger noise\nHoneybadger.beforeNotify(function (notice) {\n  if (/window\\.onunhandledrejection/.test(notice.stack)) {\n    return false\n  }\n  if (/UnhandledPromiseRejectionWarning/.test(notice.message)) {\n    return false\n  }\n  if (/window\\.onerror/.test(notice.name)) {\n    return false\n  }\n  if (/Failed to read the \\'buffered\\' property/.test(notice.message)) {\n    return false\n  }\n  if (/The object is in an invalid state/.test(notice.message)) {\n    return false\n  }\n  if (/Hls/.test(notice.stack)) {\n    return false\n  }\n  if (/flatMap is not a function/.test(notice.message)) {\n    return false\n  }\n})\n\n/*! modernizr 3.6.0 (Custom Build) | MIT *\n * https://modernizr.com/download/?-touchevents-setclasses !*/\n// prettier-ignore\n!function (e, n, t) { function o(e, n) { return typeof e === n } function s() { var e, n, t, s, a, i, r; for (var l in c) if (c.hasOwnProperty(l)) { if (e = [], n = c[l], n.name && (e.push(n.name.toLowerCase()), n.options && n.options.aliases && n.options.aliases.length)) for (t = 0; t < n.options.aliases.length; t++)e.push(n.options.aliases[t].toLowerCase()); for (s = o(n.fn, \"function\") ? n.fn() : n.fn, a = 0; a < e.length; a++)i = e[a], r = i.split(\".\"), 1 === r.length ? Modernizr[r[0]] = s : (!Modernizr[r[0]] || Modernizr[r[0]] instanceof Boolean || (Modernizr[r[0]] = new Boolean(Modernizr[r[0]])), Modernizr[r[0]][r[1]] = s), f.push((s ? \"\" : \"no-\") + r.join(\"-\")) } } function a(e) { var n = u.className, t = Modernizr._config.classPrefix || \"\"; if (p && (n = n.baseVal), Modernizr._config.enableJSClass) { var o = new RegExp(\"(^|\\\\s)\" + t + \"no-js(\\\\s|$)\"); n = n.replace(o, \"$1\" + t + \"js$2\") } Modernizr._config.enableClasses && (n += \" \" + t + e.join(\" \" + t), p ? u.className.baseVal = n : u.className = n) } function i() { return \"function\" != typeof n.createElement ? n.createElement(arguments[0]) : p ? n.createElementNS.call(n, \"http://www.w3.org/2000/svg\", arguments[0]) : n.createElement.apply(n, arguments) } function r() { var e = n.body; return e || (e = i(p ? \"svg\" : \"body\"), e.fake = !0), e } function l(e, t, o, s) { var a, l, f, c, d = \"modernizr\", p = i(\"div\"), h = r(); if (parseInt(o, 10)) for (; o--;)f = i(\"div\"), f.id = s ? s[o] : d + (o + 1), p.appendChild(f); return a = i(\"style\"), a.type = \"text/css\", a.id = \"s\" + d, (h.fake ? h : p).appendChild(a), h.appendChild(p), a.styleSheet ? a.styleSheet.cssText = e : a.appendChild(n.createTextNode(e)), p.id = d, h.fake && (h.style.background = \"\", h.style.overflow = \"hidden\", c = u.style.overflow, u.style.overflow = \"hidden\", u.appendChild(h)), l = t(p, e), h.fake ? (h.parentNode.removeChild(h), u.style.overflow = c, u.offsetHeight) : p.parentNode.removeChild(p), !!l } var f = [], c = [], d = { _version: \"3.6.0\", _config: { classPrefix: \"\", enableClasses: !0, enableJSClass: !0, usePrefixes: !0 }, _q: [], on: function (e, n) { var t = this; setTimeout(function () { n(t[e]) }, 0) }, addTest: function (e, n, t) { c.push({ name: e, fn: n, options: t }) }, addAsyncTest: function (e) { c.push({ name: null, fn: e }) } }, Modernizr = function () { }; Modernizr.prototype = d, Modernizr = new Modernizr; var u = n.documentElement, p = \"svg\" === u.nodeName.toLowerCase(), h = d._config.usePrefixes ? \" -webkit- -moz- -o- -ms- \".split(\" \") : [\"\", \"\"]; d._prefixes = h; var m = d.testStyles = l; Modernizr.addTest(\"touchevents\", function () { var t; if (\"ontouchstart\" in e || e.DocumentTouch && n instanceof DocumentTouch) t = !0; else { var o = [\"@media (\", h.join(\"touch-enabled),(\"), \"heartz\", \")\", \"{#modernizr{top:9px;position:absolute}}\"].join(\"\"); m(o, function (e) { t = 9 === e.offsetTop }) } return t }), s(), a(f), delete d.addTest, delete d.addAsyncTest; for (var v = 0; v < Modernizr._q.length; v++)Modernizr._q[v](); e.Modernizr = Modernizr }(window, document);\n", "export default ({\n  showPasswordForm = false,\n  editingEmail = false,\n  editingPassword = false,\n  newEmail = '',\n  loading = false,\n}) => ({\n  showPasswordForm,\n  editingEmail,\n  editingPassword,\n  newEmail,\n  newPassword: '',\n  loading,\n  error: null,\n  csrf: '',\n  init() {\n    this.csrf = document.querySelector('meta[name=csrf-token]').content\n  },\n  async accountFetch(url, body) {\n    this.loading = true\n    this.error = null\n\n    try {\n      const res = await fetch(url, {\n        method: 'POST',\n        headers: { 'X-CSRF-Token': this.csrf },\n        // body?\n      })\n      // handle response?\n    } catch (err) {\n      console.log(err)\n    } finally {\n      this.loading = false\n      this.editingEmail = false\n      this.editingPassword = false\n    }\n  },\n  async updateEmail(newEmail) {\n    await this.accountFetch('/account/email/new', newEmail)\n  },\n  async updatePassword(newPassword) {\n    await this.accountFetch('/account/password/new', newPassword)\n  },\n})\n", "import copy from 'copy-to-clipboard'\n\nexport const clipboard = () => (text) => copy(text)\n\nexport const formatMoney = () => (amount) =>\n  new Intl.NumberFormat('en-US').format(amount)\n\n// percent => 0.8 = 80%, should output as 80.0%\nexport const formatPercent = () => (percent) =>\n  Math.min(99.9, (Math.ceil(Number.parseFloat(percent) * 10) / 10).toFixed(1)) +\n  '%'\n\nexport const formatDuration = () => (duration) => {\n  const hours = Math.floor(duration / 3600)\n  const minutes = Math.floor((duration % 3600) / 60)\n  const seconds = duration % 60\n\n  return [\n    hours > 0 && hours.toString().padStart(2, '0'),\n    minutes > 0 && minutes.toString().padStart(2, '0'),\n    seconds.toString().padStart(2, '0'),\n  ]\n    .filter(Boolean)\n    .join(':')\n}\n\n// Time to next weekly reset\nexport const timeToNextWeeklyReset = () => {\n  const currentDate = new Date()\n\n  // Set the time to the next Tuesday at 13:00 UTC\n  let nextTuesday = new Date(currentDate)\n  nextTuesday.setUTCHours(13, 0, 0, 0)\n  nextTuesday.setUTCDate(\n    nextTuesday.getUTCDay() === 2 &&\n      nextTuesday.getTime() < currentDate.getTime()\n      ? currentDate.getUTCDate() + 7\n      : currentDate.getUTCDate() + ((2 - currentDate.getUTCDay() + 7) % 7)\n  )\n\n  // Calculate the time difference\n  const timeDiff = nextTuesday.getTime() - currentDate.getTime()\n\n  // Calculate the remaining days and hours\n  const daysLeft = Math.floor(timeDiff / (1000 * 60 * 60 * 24))\n  const hoursLeft = Math.ceil((timeDiff / (1000 * 60 * 60)) % 24)\n\n  return daysLeft > 0 ? daysLeft + 'd' : hoursLeft + 'h'\n}\n", "const emailForm = (path, project = null) => {\n  return {\n    isLoading: false,\n    isSuccess: false,\n    isError: false,\n    errorMessage: '',\n    email: '',\n    icon: '\uD83C\uDF89',\n    message: 'Receive updates and get notified when the project goes live.',\n    addEmail() {\n      this.isLoading = true\n      fetch(path, {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/json',\n          'X-CSRF-Token': document.querySelector('meta[name=\"csrf-token\"]')\n            .content,\n        },\n        body: JSON.stringify({\n          email: this.email,\n          project: project,\n        }),\n      })\n        .then((response) => response.json())\n        .then((data) => this.handleResponse(data))\n        .catch((error) => console.log(error))\n    },\n    handleResponse(response) {\n      if (response.status == 'ok') {\n        this.icon = '<i class=\"fas fa-thumbs-up\"></i>'\n        this.message = \"You're on the list!\"\n        this.isError = false\n        this.isSuccess = true\n      } else if (response.status == 'error') {\n        this.errorMessage = response.message\n        this.isError = true\n      }\n      this.isLoading = false\n    },\n  }\n}\n\nexport default emailForm\n", "export default ({\n  already_funded = false,\n  me_funded = 0,\n  project_balance = 0,\n  project_goal = 0,\n  episodes = [],\n}) => ({\n  already_funded,\n  me_funded,\n  project_balance,\n  project_goal,\n  episodes,\n  csrf: '',\n  init() {\n    this.csrf = document.querySelector('meta[name=csrf-token]').content\n  },\n  async fetchFirstFund(id) {\n    try {\n      const {\n        already_funded,\n        me_funded,\n        project_balance,\n        project_goal,\n        episodes,\n      } = await (\n        await fetch(`/getting_started/first_fund/${id}`, {\n          method: 'POST',\n          headers: { 'X-CSRF-Token': this.csrf },\n        })\n      ).json()\n\n      this.already_funded = already_funded\n      this.me_funded = me_funded\n      this.project_balance = project_balance\n      this.project_goal = project_goal\n      this.episodes = episodes\n    } catch (err) {\n      console.log(err)\n    }\n  },\n})\n", "/*! @vimeo/player v2.19.0 | (c) 2023 Vimeo | MIT License | https://github.com/vimeo/player.js */\nfunction _classCallCheck(instance, Constructor) {\n  if (!(instance instanceof Constructor)) {\n    throw new TypeError(\"Cannot call a class as a function\");\n  }\n}\n\nfunction _defineProperties(target, props) {\n  for (var i = 0; i < props.length; i++) {\n    var descriptor = props[i];\n    descriptor.enumerable = descriptor.enumerable || false;\n    descriptor.configurable = true;\n    if (\"value\" in descriptor) descriptor.writable = true;\n    Object.defineProperty(target, descriptor.key, descriptor);\n  }\n}\n\nfunction _createClass(Constructor, protoProps, staticProps) {\n  if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n  if (staticProps) _defineProperties(Constructor, staticProps);\n  return Constructor;\n}\n\n/**\n * @module lib/functions\n */\n\n/**\n * Check to see this is a node environment.\n * @type {Boolean}\n */\n\n/* global global */\nvar isNode = typeof global !== 'undefined' && {}.toString.call(global) === '[object global]';\n/**\n * Get the name of the method for a given getter or setter.\n *\n * @param {string} prop The name of the property.\n * @param {string} type Either \u201Cget\u201D or \u201Cset\u201D.\n * @return {string}\n */\n\nfunction getMethodName(prop, type) {\n  if (prop.indexOf(type.toLowerCase()) === 0) {\n    return prop;\n  }\n\n  return \"\".concat(type.toLowerCase()).concat(prop.substr(0, 1).toUpperCase()).concat(prop.substr(1));\n}\n/**\n * Check to see if the object is a DOM Element.\n *\n * @param {*} element The object to check.\n * @return {boolean}\n */\n\nfunction isDomElement(element) {\n  return Boolean(element && element.nodeType === 1 && 'nodeName' in element && element.ownerDocument && element.ownerDocument.defaultView);\n}\n/**\n * Check to see whether the value is a number.\n *\n * @see http://dl.dropboxusercontent.com/u/35146/js/tests/isNumber.html\n * @param {*} value The value to check.\n * @param {boolean} integer Check if the value is an integer.\n * @return {boolean}\n */\n\nfunction isInteger(value) {\n  // eslint-disable-next-line eqeqeq\n  return !isNaN(parseFloat(value)) && isFinite(value) && Math.floor(value) == value;\n}\n/**\n * Check to see if the URL is a Vimeo url.\n *\n * @param {string} url The url string.\n * @return {boolean}\n */\n\nfunction isVimeoUrl(url) {\n  return /^(https?:)?\\/\\/((player|www)\\.)?vimeo\\.com(?=$|\\/)/.test(url);\n}\n/**\n * Check to see if the URL is for a Vimeo embed.\n *\n * @param {string} url The url string.\n * @return {boolean}\n */\n\nfunction isVimeoEmbed(url) {\n  var expr = /^https:\\/\\/player\\.vimeo\\.com\\/video\\/\\d+/;\n  return expr.test(url);\n}\n/**\n * Get the Vimeo URL from an element.\n * The element must have either a data-vimeo-id or data-vimeo-url attribute.\n *\n * @param {object} oEmbedParameters The oEmbed parameters.\n * @return {string}\n */\n\nfunction getVimeoUrl() {\n  var oEmbedParameters = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n  var id = oEmbedParameters.id;\n  var url = oEmbedParameters.url;\n  var idOrUrl = id || url;\n\n  if (!idOrUrl) {\n    throw new Error('An id or url must be passed, either in an options object or as a data-vimeo-id or data-vimeo-url attribute.');\n  }\n\n  if (isInteger(idOrUrl)) {\n    return \"https://vimeo.com/\".concat(idOrUrl);\n  }\n\n  if (isVimeoUrl(idOrUrl)) {\n    return idOrUrl.replace('http:', 'https:');\n  }\n\n  if (id) {\n    throw new TypeError(\"\\u201C\".concat(id, \"\\u201D is not a valid video id.\"));\n  }\n\n  throw new TypeError(\"\\u201C\".concat(idOrUrl, \"\\u201D is not a vimeo.com url.\"));\n}\n\nvar arrayIndexOfSupport = typeof Array.prototype.indexOf !== 'undefined';\nvar postMessageSupport = typeof window !== 'undefined' && typeof window.postMessage !== 'undefined';\n\nif (!isNode && (!arrayIndexOfSupport || !postMessageSupport)) {\n  throw new Error('Sorry, the Vimeo Player API is not available in this browser.');\n}\n\nvar commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};\n\nfunction createCommonjsModule(fn, module) {\n\treturn module = { exports: {} }, fn(module, module.exports), module.exports;\n}\n\n/*!\n * weakmap-polyfill v2.0.4 - ECMAScript6 WeakMap polyfill\n * https://github.com/polygonplanet/weakmap-polyfill\n * Copyright (c) 2015-2021 polygonplanet <polygon.planet.aqua@gmail.com>\n * @license MIT\n */\n(function (self) {\n\n  if (self.WeakMap) {\n    return;\n  }\n\n  var hasOwnProperty = Object.prototype.hasOwnProperty;\n\n  var hasDefine = Object.defineProperty && function () {\n    try {\n      // Avoid IE8's broken Object.defineProperty\n      return Object.defineProperty({}, 'x', {\n        value: 1\n      }).x === 1;\n    } catch (e) {}\n  }();\n\n  var defineProperty = function (object, name, value) {\n    if (hasDefine) {\n      Object.defineProperty(object, name, {\n        configurable: true,\n        writable: true,\n        value: value\n      });\n    } else {\n      object[name] = value;\n    }\n  };\n\n  self.WeakMap = function () {\n    // ECMA-262 23.3 WeakMap Objects\n    function WeakMap() {\n      if (this === void 0) {\n        throw new TypeError(\"Constructor WeakMap requires 'new'\");\n      }\n\n      defineProperty(this, '_id', genId('_WeakMap')); // ECMA-262 23.3.1.1 WeakMap([iterable])\n\n      if (arguments.length > 0) {\n        // Currently, WeakMap `iterable` argument is not supported\n        throw new TypeError('WeakMap iterable is not supported');\n      }\n    } // ECMA-262 23.3.3.2 WeakMap.prototype.delete(key)\n\n\n    defineProperty(WeakMap.prototype, 'delete', function (key) {\n      checkInstance(this, 'delete');\n\n      if (!isObject(key)) {\n        return false;\n      }\n\n      var entry = key[this._id];\n\n      if (entry && entry[0] === key) {\n        delete key[this._id];\n        return true;\n      }\n\n      return false;\n    }); // ECMA-262 23.3.3.3 WeakMap.prototype.get(key)\n\n    defineProperty(WeakMap.prototype, 'get', function (key) {\n      checkInstance(this, 'get');\n\n      if (!isObject(key)) {\n        return void 0;\n      }\n\n      var entry = key[this._id];\n\n      if (entry && entry[0] === key) {\n        return entry[1];\n      }\n\n      return void 0;\n    }); // ECMA-262 23.3.3.4 WeakMap.prototype.has(key)\n\n    defineProperty(WeakMap.prototype, 'has', function (key) {\n      checkInstance(this, 'has');\n\n      if (!isObject(key)) {\n        return false;\n      }\n\n      var entry = key[this._id];\n\n      if (entry && entry[0] === key) {\n        return true;\n      }\n\n      return false;\n    }); // ECMA-262 23.3.3.5 WeakMap.prototype.set(key, value)\n\n    defineProperty(WeakMap.prototype, 'set', function (key, value) {\n      checkInstance(this, 'set');\n\n      if (!isObject(key)) {\n        throw new TypeError('Invalid value used as weak map key');\n      }\n\n      var entry = key[this._id];\n\n      if (entry && entry[0] === key) {\n        entry[1] = value;\n        return this;\n      }\n\n      defineProperty(key, this._id, [key, value]);\n      return this;\n    });\n\n    function checkInstance(x, methodName) {\n      if (!isObject(x) || !hasOwnProperty.call(x, '_id')) {\n        throw new TypeError(methodName + ' method called on incompatible receiver ' + typeof x);\n      }\n    }\n\n    function genId(prefix) {\n      return prefix + '_' + rand() + '.' + rand();\n    }\n\n    function rand() {\n      return Math.random().toString().substring(2);\n    }\n\n    defineProperty(WeakMap, '_polyfill', true);\n    return WeakMap;\n  }();\n\n  function isObject(x) {\n    return Object(x) === x;\n  }\n})(typeof globalThis !== 'undefined' ? globalThis : typeof self !== 'undefined' ? self : typeof window !== 'undefined' ? window : typeof commonjsGlobal !== 'undefined' ? commonjsGlobal : commonjsGlobal);\n\nvar npo_src = createCommonjsModule(function (module) {\n/*! Native Promise Only\n    v0.8.1 (c) Kyle Simpson\n    MIT License: http://getify.mit-license.org\n*/\n(function UMD(name, context, definition) {\n  // special form of UMD for polyfilling across evironments\n  context[name] = context[name] || definition();\n\n  if ( module.exports) {\n    module.exports = context[name];\n  }\n})(\"Promise\", typeof commonjsGlobal != \"undefined\" ? commonjsGlobal : commonjsGlobal, function DEF() {\n\n  var builtInProp,\n      cycle,\n      scheduling_queue,\n      ToString = Object.prototype.toString,\n      timer = typeof setImmediate != \"undefined\" ? function timer(fn) {\n    return setImmediate(fn);\n  } : setTimeout; // dammit, IE8.\n\n  try {\n    Object.defineProperty({}, \"x\", {});\n\n    builtInProp = function builtInProp(obj, name, val, config) {\n      return Object.defineProperty(obj, name, {\n        value: val,\n        writable: true,\n        configurable: config !== false\n      });\n    };\n  } catch (err) {\n    builtInProp = function builtInProp(obj, name, val) {\n      obj[name] = val;\n      return obj;\n    };\n  } // Note: using a queue instead of array for efficiency\n\n\n  scheduling_queue = function Queue() {\n    var first, last, item;\n\n    function Item(fn, self) {\n      this.fn = fn;\n      this.self = self;\n      this.next = void 0;\n    }\n\n    return {\n      add: function add(fn, self) {\n        item = new Item(fn, self);\n\n        if (last) {\n          last.next = item;\n        } else {\n          first = item;\n        }\n\n        last = item;\n        item = void 0;\n      },\n      drain: function drain() {\n        var f = first;\n        first = last = cycle = void 0;\n\n        while (f) {\n          f.fn.call(f.self);\n          f = f.next;\n        }\n      }\n    };\n  }();\n\n  function schedule(fn, self) {\n    scheduling_queue.add(fn, self);\n\n    if (!cycle) {\n      cycle = timer(scheduling_queue.drain);\n    }\n  } // promise duck typing\n\n\n  function isThenable(o) {\n    var _then,\n        o_type = typeof o;\n\n    if (o != null && (o_type == \"object\" || o_type == \"function\")) {\n      _then = o.then;\n    }\n\n    return typeof _then == \"function\" ? _then : false;\n  }\n\n  function notify() {\n    for (var i = 0; i < this.chain.length; i++) {\n      notifyIsolated(this, this.state === 1 ? this.chain[i].success : this.chain[i].failure, this.chain[i]);\n    }\n\n    this.chain.length = 0;\n  } // NOTE: This is a separate function to isolate\n  // the `try..catch` so that other code can be\n  // optimized better\n\n\n  function notifyIsolated(self, cb, chain) {\n    var ret, _then;\n\n    try {\n      if (cb === false) {\n        chain.reject(self.msg);\n      } else {\n        if (cb === true) {\n          ret = self.msg;\n        } else {\n          ret = cb.call(void 0, self.msg);\n        }\n\n        if (ret === chain.promise) {\n          chain.reject(TypeError(\"Promise-chain cycle\"));\n        } else if (_then = isThenable(ret)) {\n          _then.call(ret, chain.resolve, chain.reject);\n        } else {\n          chain.resolve(ret);\n        }\n      }\n    } catch (err) {\n      chain.reject(err);\n    }\n  }\n\n  function resolve(msg) {\n    var _then,\n        self = this; // already triggered?\n\n\n    if (self.triggered) {\n      return;\n    }\n\n    self.triggered = true; // unwrap\n\n    if (self.def) {\n      self = self.def;\n    }\n\n    try {\n      if (_then = isThenable(msg)) {\n        schedule(function () {\n          var def_wrapper = new MakeDefWrapper(self);\n\n          try {\n            _then.call(msg, function $resolve$() {\n              resolve.apply(def_wrapper, arguments);\n            }, function $reject$() {\n              reject.apply(def_wrapper, arguments);\n            });\n          } catch (err) {\n            reject.call(def_wrapper, err);\n          }\n        });\n      } else {\n        self.msg = msg;\n        self.state = 1;\n\n        if (self.chain.length > 0) {\n          schedule(notify, self);\n        }\n      }\n    } catch (err) {\n      reject.call(new MakeDefWrapper(self), err);\n    }\n  }\n\n  function reject(msg) {\n    var self = this; // already triggered?\n\n    if (self.triggered) {\n      return;\n    }\n\n    self.triggered = true; // unwrap\n\n    if (self.def) {\n      self = self.def;\n    }\n\n    self.msg = msg;\n    self.state = 2;\n\n    if (self.chain.length > 0) {\n      schedule(notify, self);\n    }\n  }\n\n  function iteratePromises(Constructor, arr, resolver, rejecter) {\n    for (var idx = 0; idx < arr.length; idx++) {\n      (function IIFE(idx) {\n        Constructor.resolve(arr[idx]).then(function $resolver$(msg) {\n          resolver(idx, msg);\n        }, rejecter);\n      })(idx);\n    }\n  }\n\n  function MakeDefWrapper(self) {\n    this.def = self;\n    this.triggered = false;\n  }\n\n  function MakeDef(self) {\n    this.promise = self;\n    this.state = 0;\n    this.triggered = false;\n    this.chain = [];\n    this.msg = void 0;\n  }\n\n  function Promise(executor) {\n    if (typeof executor != \"function\") {\n      throw TypeError(\"Not a function\");\n    }\n\n    if (this.__NPO__ !== 0) {\n      throw TypeError(\"Not a promise\");\n    } // instance shadowing the inherited \"brand\"\n    // to signal an already \"initialized\" promise\n\n\n    this.__NPO__ = 1;\n    var def = new MakeDef(this);\n\n    this[\"then\"] = function then(success, failure) {\n      var o = {\n        success: typeof success == \"function\" ? success : true,\n        failure: typeof failure == \"function\" ? failure : false\n      }; // Note: `then(..)` itself can be borrowed to be used against\n      // a different promise constructor for making the chained promise,\n      // by substituting a different `this` binding.\n\n      o.promise = new this.constructor(function extractChain(resolve, reject) {\n        if (typeof resolve != \"function\" || typeof reject != \"function\") {\n          throw TypeError(\"Not a function\");\n        }\n\n        o.resolve = resolve;\n        o.reject = reject;\n      });\n      def.chain.push(o);\n\n      if (def.state !== 0) {\n        schedule(notify, def);\n      }\n\n      return o.promise;\n    };\n\n    this[\"catch\"] = function $catch$(failure) {\n      return this.then(void 0, failure);\n    };\n\n    try {\n      executor.call(void 0, function publicResolve(msg) {\n        resolve.call(def, msg);\n      }, function publicReject(msg) {\n        reject.call(def, msg);\n      });\n    } catch (err) {\n      reject.call(def, err);\n    }\n  }\n\n  var PromisePrototype = builtInProp({}, \"constructor\", Promise,\n  /*configurable=*/\n  false); // Note: Android 4 cannot use `Object.defineProperty(..)` here\n\n  Promise.prototype = PromisePrototype; // built-in \"brand\" to signal an \"uninitialized\" promise\n\n  builtInProp(PromisePrototype, \"__NPO__\", 0,\n  /*configurable=*/\n  false);\n  builtInProp(Promise, \"resolve\", function Promise$resolve(msg) {\n    var Constructor = this; // spec mandated checks\n    // note: best \"isPromise\" check that's practical for now\n\n    if (msg && typeof msg == \"object\" && msg.__NPO__ === 1) {\n      return msg;\n    }\n\n    return new Constructor(function executor(resolve, reject) {\n      if (typeof resolve != \"function\" || typeof reject != \"function\") {\n        throw TypeError(\"Not a function\");\n      }\n\n      resolve(msg);\n    });\n  });\n  builtInProp(Promise, \"reject\", function Promise$reject(msg) {\n    return new this(function executor(resolve, reject) {\n      if (typeof resolve != \"function\" || typeof reject != \"function\") {\n        throw TypeError(\"Not a function\");\n      }\n\n      reject(msg);\n    });\n  });\n  builtInProp(Promise, \"all\", function Promise$all(arr) {\n    var Constructor = this; // spec mandated checks\n\n    if (ToString.call(arr) != \"[object Array]\") {\n      return Constructor.reject(TypeError(\"Not an array\"));\n    }\n\n    if (arr.length === 0) {\n      return Constructor.resolve([]);\n    }\n\n    return new Constructor(function executor(resolve, reject) {\n      if (typeof resolve != \"function\" || typeof reject != \"function\") {\n        throw TypeError(\"Not a function\");\n      }\n\n      var len = arr.length,\n          msgs = Array(len),\n          count = 0;\n      iteratePromises(Constructor, arr, function resolver(idx, msg) {\n        msgs[idx] = msg;\n\n        if (++count === len) {\n          resolve(msgs);\n        }\n      }, reject);\n    });\n  });\n  builtInProp(Promise, \"race\", function Promise$race(arr) {\n    var Constructor = this; // spec mandated checks\n\n    if (ToString.call(arr) != \"[object Array]\") {\n      return Constructor.reject(TypeError(\"Not an array\"));\n    }\n\n    return new Constructor(function executor(resolve, reject) {\n      if (typeof resolve != \"function\" || typeof reject != \"function\") {\n        throw TypeError(\"Not a function\");\n      }\n\n      iteratePromises(Constructor, arr, function resolver(idx, msg) {\n        resolve(msg);\n      }, reject);\n    });\n  });\n  return Promise;\n});\n});\n\n/**\n * @module lib/callbacks\n */\nvar callbackMap = new WeakMap();\n/**\n * Store a callback for a method or event for a player.\n *\n * @param {Player} player The player object.\n * @param {string} name The method or event name.\n * @param {(function(this:Player, *): void|{resolve: function, reject: function})} callback\n *        The callback to call or an object with resolve and reject functions for a promise.\n * @return {void}\n */\n\nfunction storeCallback(player, name, callback) {\n  var playerCallbacks = callbackMap.get(player.element) || {};\n\n  if (!(name in playerCallbacks)) {\n    playerCallbacks[name] = [];\n  }\n\n  playerCallbacks[name].push(callback);\n  callbackMap.set(player.element, playerCallbacks);\n}\n/**\n * Get the callbacks for a player and event or method.\n *\n * @param {Player} player The player object.\n * @param {string} name The method or event name\n * @return {function[]}\n */\n\nfunction getCallbacks(player, name) {\n  var playerCallbacks = callbackMap.get(player.element) || {};\n  return playerCallbacks[name] || [];\n}\n/**\n * Remove a stored callback for a method or event for a player.\n *\n * @param {Player} player The player object.\n * @param {string} name The method or event name\n * @param {function} [callback] The specific callback to remove.\n * @return {boolean} Was this the last callback?\n */\n\nfunction removeCallback(player, name, callback) {\n  var playerCallbacks = callbackMap.get(player.element) || {};\n\n  if (!playerCallbacks[name]) {\n    return true;\n  } // If no callback is passed, remove all callbacks for the event\n\n\n  if (!callback) {\n    playerCallbacks[name] = [];\n    callbackMap.set(player.element, playerCallbacks);\n    return true;\n  }\n\n  var index = playerCallbacks[name].indexOf(callback);\n\n  if (index !== -1) {\n    playerCallbacks[name].splice(index, 1);\n  }\n\n  callbackMap.set(player.element, playerCallbacks);\n  return playerCallbacks[name] && playerCallbacks[name].length === 0;\n}\n/**\n * Return the first stored callback for a player and event or method.\n *\n * @param {Player} player The player object.\n * @param {string} name The method or event name.\n * @return {function} The callback, or false if there were none\n */\n\nfunction shiftCallbacks(player, name) {\n  var playerCallbacks = getCallbacks(player, name);\n\n  if (playerCallbacks.length < 1) {\n    return false;\n  }\n\n  var callback = playerCallbacks.shift();\n  removeCallback(player, name, callback);\n  return callback;\n}\n/**\n * Move callbacks associated with an element to another element.\n *\n * @param {HTMLElement} oldElement The old element.\n * @param {HTMLElement} newElement The new element.\n * @return {void}\n */\n\nfunction swapCallbacks(oldElement, newElement) {\n  var playerCallbacks = callbackMap.get(oldElement);\n  callbackMap.set(newElement, playerCallbacks);\n  callbackMap.delete(oldElement);\n}\n\n/**\n * @module lib/postmessage\n */\n/**\n * Parse a message received from postMessage.\n *\n * @param {*} data The data received from postMessage.\n * @return {object}\n */\n\nfunction parseMessageData(data) {\n  if (typeof data === 'string') {\n    try {\n      data = JSON.parse(data);\n    } catch (error) {\n      // If the message cannot be parsed, throw the error as a warning\n      console.warn(error);\n      return {};\n    }\n  }\n\n  return data;\n}\n/**\n * Post a message to the specified target.\n *\n * @param {Player} player The player object to use.\n * @param {string} method The API method to call.\n * @param {object} params The parameters to send to the player.\n * @return {void}\n */\n\nfunction postMessage(player, method, params) {\n  if (!player.element.contentWindow || !player.element.contentWindow.postMessage) {\n    return;\n  }\n\n  var message = {\n    method: method\n  };\n\n  if (params !== undefined) {\n    message.value = params;\n  } // IE 8 and 9 do not support passing messages, so stringify them\n\n\n  var ieVersion = parseFloat(navigator.userAgent.toLowerCase().replace(/^.*msie (\\d+).*$/, '$1'));\n\n  if (ieVersion >= 8 && ieVersion < 10) {\n    message = JSON.stringify(message);\n  }\n\n  player.element.contentWindow.postMessage(message, player.origin);\n}\n/**\n * Parse the data received from a message event.\n *\n * @param {Player} player The player that received the message.\n * @param {(Object|string)} data The message data. Strings will be parsed into JSON.\n * @return {void}\n */\n\nfunction processData(player, data) {\n  data = parseMessageData(data);\n  var callbacks = [];\n  var param;\n\n  if (data.event) {\n    if (data.event === 'error') {\n      var promises = getCallbacks(player, data.data.method);\n      promises.forEach(function (promise) {\n        var error = new Error(data.data.message);\n        error.name = data.data.name;\n        promise.reject(error);\n        removeCallback(player, data.data.method, promise);\n      });\n    }\n\n    callbacks = getCallbacks(player, \"event:\".concat(data.event));\n    param = data.data;\n  } else if (data.method) {\n    var callback = shiftCallbacks(player, data.method);\n\n    if (callback) {\n      callbacks.push(callback);\n      param = data.value;\n    }\n  }\n\n  callbacks.forEach(function (callback) {\n    try {\n      if (typeof callback === 'function') {\n        callback.call(player, param);\n        return;\n      }\n\n      callback.resolve(param);\n    } catch (e) {// empty\n    }\n  });\n}\n\n/**\n * @module lib/embed\n */\nvar oEmbedParameters = ['autopause', 'autoplay', 'background', 'byline', 'color', 'controls', 'dnt', 'height', 'id', 'interactive_params', 'keyboard', 'loop', 'maxheight', 'maxwidth', 'muted', 'playsinline', 'portrait', 'responsive', 'speed', 'texttrack', 'title', 'transparent', 'url', 'width'];\n/**\n * Get the 'data-vimeo'-prefixed attributes from an element as an object.\n *\n * @param {HTMLElement} element The element.\n * @param {Object} [defaults={}] The default values to use.\n * @return {Object<string, string>}\n */\n\nfunction getOEmbedParameters(element) {\n  var defaults = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n  return oEmbedParameters.reduce(function (params, param) {\n    var value = element.getAttribute(\"data-vimeo-\".concat(param));\n\n    if (value || value === '') {\n      params[param] = value === '' ? 1 : value;\n    }\n\n    return params;\n  }, defaults);\n}\n/**\n * Create an embed from oEmbed data inside an element.\n *\n * @param {object} data The oEmbed data.\n * @param {HTMLElement} element The element to put the iframe in.\n * @return {HTMLIFrameElement} The iframe embed.\n */\n\nfunction createEmbed(_ref, element) {\n  var html = _ref.html;\n\n  if (!element) {\n    throw new TypeError('An element must be provided');\n  }\n\n  if (element.getAttribute('data-vimeo-initialized') !== null) {\n    return element.querySelector('iframe');\n  }\n\n  var div = document.createElement('div');\n  div.innerHTML = html;\n  element.appendChild(div.firstChild);\n  element.setAttribute('data-vimeo-initialized', 'true');\n  return element.querySelector('iframe');\n}\n/**\n * Make an oEmbed call for the specified URL.\n *\n * @param {string} videoUrl The vimeo.com url for the video.\n * @param {Object} [params] Parameters to pass to oEmbed.\n * @param {HTMLElement} element The element.\n * @return {Promise}\n */\n\nfunction getOEmbedData(videoUrl) {\n  var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n  var element = arguments.length > 2 ? arguments[2] : undefined;\n  return new Promise(function (resolve, reject) {\n    if (!isVimeoUrl(videoUrl)) {\n      throw new TypeError(\"\\u201C\".concat(videoUrl, \"\\u201D is not a vimeo.com url.\"));\n    }\n\n    var url = \"https://vimeo.com/api/oembed.json?url=\".concat(encodeURIComponent(videoUrl));\n\n    for (var param in params) {\n      if (params.hasOwnProperty(param)) {\n        url += \"&\".concat(param, \"=\").concat(encodeURIComponent(params[param]));\n      }\n    }\n\n    var xhr = 'XDomainRequest' in window ? new XDomainRequest() : new XMLHttpRequest();\n    xhr.open('GET', url, true);\n\n    xhr.onload = function () {\n      if (xhr.status === 404) {\n        reject(new Error(\"\\u201C\".concat(videoUrl, \"\\u201D was not found.\")));\n        return;\n      }\n\n      if (xhr.status === 403) {\n        reject(new Error(\"\\u201C\".concat(videoUrl, \"\\u201D is not embeddable.\")));\n        return;\n      }\n\n      try {\n        var json = JSON.parse(xhr.responseText); // Check api response for 403 on oembed\n\n        if (json.domain_status_code === 403) {\n          // We still want to create the embed to give users visual feedback\n          createEmbed(json, element);\n          reject(new Error(\"\\u201C\".concat(videoUrl, \"\\u201D is not embeddable.\")));\n          return;\n        }\n\n        resolve(json);\n      } catch (error) {\n        reject(error);\n      }\n    };\n\n    xhr.onerror = function () {\n      var status = xhr.status ? \" (\".concat(xhr.status, \")\") : '';\n      reject(new Error(\"There was an error fetching the embed code from Vimeo\".concat(status, \".\")));\n    };\n\n    xhr.send();\n  });\n}\n/**\n * Initialize all embeds within a specific element\n *\n * @param {HTMLElement} [parent=document] The parent element.\n * @return {void}\n */\n\nfunction initializeEmbeds() {\n  var parent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : document;\n  var elements = [].slice.call(parent.querySelectorAll('[data-vimeo-id], [data-vimeo-url]'));\n\n  var handleError = function handleError(error) {\n    if ('console' in window && console.error) {\n      console.error(\"There was an error creating an embed: \".concat(error));\n    }\n  };\n\n  elements.forEach(function (element) {\n    try {\n      // Skip any that have data-vimeo-defer\n      if (element.getAttribute('data-vimeo-defer') !== null) {\n        return;\n      }\n\n      var params = getOEmbedParameters(element);\n      var url = getVimeoUrl(params);\n      getOEmbedData(url, params, element).then(function (data) {\n        return createEmbed(data, element);\n      }).catch(handleError);\n    } catch (error) {\n      handleError(error);\n    }\n  });\n}\n/**\n * Resize embeds when messaged by the player.\n *\n * @param {HTMLElement} [parent=document] The parent element.\n * @return {void}\n */\n\nfunction resizeEmbeds() {\n  var parent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : document;\n\n  // Prevent execution if users include the player.js script multiple times.\n  if (window.VimeoPlayerResizeEmbeds_) {\n    return;\n  }\n\n  window.VimeoPlayerResizeEmbeds_ = true;\n\n  var onMessage = function onMessage(event) {\n    if (!isVimeoUrl(event.origin)) {\n      return;\n    } // 'spacechange' is fired only on embeds with cards\n\n\n    if (!event.data || event.data.event !== 'spacechange') {\n      return;\n    }\n\n    var iframes = parent.querySelectorAll('iframe');\n\n    for (var i = 0; i < iframes.length; i++) {\n      if (iframes[i].contentWindow !== event.source) {\n        continue;\n      } // Change padding-bottom of the enclosing div to accommodate\n      // card carousel without distorting aspect ratio\n\n\n      var space = iframes[i].parentElement;\n      space.style.paddingBottom = \"\".concat(event.data.data[0].bottom, \"px\");\n      break;\n    }\n  };\n\n  window.addEventListener('message', onMessage);\n}\n/**\n * Add chapters to existing metadata for Google SEO\n *\n * @param {HTMLElement} [parent=document] The parent element.\n * @return {void}\n */\n\nfunction initAppendVideoMetadata() {\n  var parent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : document;\n\n  //  Prevent execution if users include the player.js script multiple times.\n  if (window.VimeoSeoMetadataAppended) {\n    return;\n  }\n\n  window.VimeoSeoMetadataAppended = true;\n\n  var onMessage = function onMessage(event) {\n    if (!isVimeoUrl(event.origin)) {\n      return;\n    }\n\n    var data = parseMessageData(event.data);\n\n    if (!data || data.event !== 'ready') {\n      return;\n    }\n\n    var iframes = parent.querySelectorAll('iframe');\n\n    for (var i = 0; i < iframes.length; i++) {\n      var iframe = iframes[i]; // Initiate appendVideoMetadata if iframe is a Vimeo embed\n\n      var isValidMessageSource = iframe.contentWindow === event.source;\n\n      if (isVimeoEmbed(iframe.src) && isValidMessageSource) {\n        var player = new Player(iframe);\n        player.callMethod('appendVideoMetadata', window.location.href);\n      }\n    }\n  };\n\n  window.addEventListener('message', onMessage);\n}\n/**\n * Seek to time indicated by vimeo_t query parameter if present in URL\n *\n * @param {HTMLElement} [parent=document] The parent element.\n * @return {void}\n */\n\nfunction checkUrlTimeParam() {\n  var parent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : document;\n\n  //  Prevent execution if users include the player.js script multiple times.\n  if (window.VimeoCheckedUrlTimeParam) {\n    return;\n  }\n\n  window.VimeoCheckedUrlTimeParam = true;\n\n  var handleError = function handleError(error) {\n    if ('console' in window && console.error) {\n      console.error(\"There was an error getting video Id: \".concat(error));\n    }\n  };\n\n  var onMessage = function onMessage(event) {\n    if (!isVimeoUrl(event.origin)) {\n      return;\n    }\n\n    var data = parseMessageData(event.data);\n\n    if (!data || data.event !== 'ready') {\n      return;\n    }\n\n    var iframes = parent.querySelectorAll('iframe');\n\n    for (var i = 0; i < iframes.length; i++) {\n      var iframe = iframes[i];\n      var isValidMessageSource = iframe.contentWindow === event.source;\n\n      if (isVimeoEmbed(iframe.src) && isValidMessageSource) {\n        (function () {\n          var player = new Player(iframe);\n          player.getVideoId().then(function (videoId) {\n            var matches = new RegExp(\"[?&]vimeo_t_\".concat(videoId, \"=([^&#]*)\")).exec(window.location.href);\n\n            if (matches && matches[1]) {\n              var sec = decodeURI(matches[1]);\n              player.setCurrentTime(sec);\n            }\n\n            return;\n          }).catch(handleError);\n        })();\n      }\n    }\n  };\n\n  window.addEventListener('message', onMessage);\n}\n\n/* MIT License\n\nCopyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\nTerms */\nfunction initializeScreenfull() {\n  var fn = function () {\n    var val;\n    var fnMap = [['requestFullscreen', 'exitFullscreen', 'fullscreenElement', 'fullscreenEnabled', 'fullscreenchange', 'fullscreenerror'], // New WebKit\n    ['webkitRequestFullscreen', 'webkitExitFullscreen', 'webkitFullscreenElement', 'webkitFullscreenEnabled', 'webkitfullscreenchange', 'webkitfullscreenerror'], // Old WebKit\n    ['webkitRequestFullScreen', 'webkitCancelFullScreen', 'webkitCurrentFullScreenElement', 'webkitCancelFullScreen', 'webkitfullscreenchange', 'webkitfullscreenerror'], ['mozRequestFullScreen', 'mozCancelFullScreen', 'mozFullScreenElement', 'mozFullScreenEnabled', 'mozfullscreenchange', 'mozfullscreenerror'], ['msRequestFullscreen', 'msExitFullscreen', 'msFullscreenElement', 'msFullscreenEnabled', 'MSFullscreenChange', 'MSFullscreenError']];\n    var i = 0;\n    var l = fnMap.length;\n    var ret = {};\n\n    for (; i < l; i++) {\n      val = fnMap[i];\n\n      if (val && val[1] in document) {\n        for (i = 0; i < val.length; i++) {\n          ret[fnMap[0][i]] = val[i];\n        }\n\n        return ret;\n      }\n    }\n\n    return false;\n  }();\n\n  var eventNameMap = {\n    fullscreenchange: fn.fullscreenchange,\n    fullscreenerror: fn.fullscreenerror\n  };\n  var screenfull = {\n    request: function request(element) {\n      return new Promise(function (resolve, reject) {\n        var onFullScreenEntered = function onFullScreenEntered() {\n          screenfull.off('fullscreenchange', onFullScreenEntered);\n          resolve();\n        };\n\n        screenfull.on('fullscreenchange', onFullScreenEntered);\n        element = element || document.documentElement;\n        var returnPromise = element[fn.requestFullscreen]();\n\n        if (returnPromise instanceof Promise) {\n          returnPromise.then(onFullScreenEntered).catch(reject);\n        }\n      });\n    },\n    exit: function exit() {\n      return new Promise(function (resolve, reject) {\n        if (!screenfull.isFullscreen) {\n          resolve();\n          return;\n        }\n\n        var onFullScreenExit = function onFullScreenExit() {\n          screenfull.off('fullscreenchange', onFullScreenExit);\n          resolve();\n        };\n\n        screenfull.on('fullscreenchange', onFullScreenExit);\n        var returnPromise = document[fn.exitFullscreen]();\n\n        if (returnPromise instanceof Promise) {\n          returnPromise.then(onFullScreenExit).catch(reject);\n        }\n      });\n    },\n    on: function on(event, callback) {\n      var eventName = eventNameMap[event];\n\n      if (eventName) {\n        document.addEventListener(eventName, callback);\n      }\n    },\n    off: function off(event, callback) {\n      var eventName = eventNameMap[event];\n\n      if (eventName) {\n        document.removeEventListener(eventName, callback);\n      }\n    }\n  };\n  Object.defineProperties(screenfull, {\n    isFullscreen: {\n      get: function get() {\n        return Boolean(document[fn.fullscreenElement]);\n      }\n    },\n    element: {\n      enumerable: true,\n      get: function get() {\n        return document[fn.fullscreenElement];\n      }\n    },\n    isEnabled: {\n      enumerable: true,\n      get: function get() {\n        // Coerce to boolean in case of old WebKit\n        return Boolean(document[fn.fullscreenEnabled]);\n      }\n    }\n  });\n  return screenfull;\n}\n\nvar playerMap = new WeakMap();\nvar readyMap = new WeakMap();\nvar screenfull = {};\n\nvar Player = /*#__PURE__*/function () {\n  /**\n   * Create a Player.\n   *\n   * @param {(HTMLIFrameElement|HTMLElement|string|jQuery)} element A reference to the Vimeo\n   *        player iframe, and id, or a jQuery object.\n   * @param {object} [options] oEmbed parameters to use when creating an embed in the element.\n   * @return {Player}\n   */\n  function Player(element) {\n    var _this = this;\n\n    var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n\n    _classCallCheck(this, Player);\n\n    /* global jQuery */\n    if (window.jQuery && element instanceof jQuery) {\n      if (element.length > 1 && window.console && console.warn) {\n        console.warn('A jQuery object with multiple elements was passed, using the first element.');\n      }\n\n      element = element[0];\n    } // Find an element by ID\n\n\n    if (typeof document !== 'undefined' && typeof element === 'string') {\n      element = document.getElementById(element);\n    } // Not an element!\n\n\n    if (!isDomElement(element)) {\n      throw new TypeError('You must pass either a valid element or a valid id.');\n    } // Already initialized an embed in this div, so grab the iframe\n\n\n    if (element.nodeName !== 'IFRAME') {\n      var iframe = element.querySelector('iframe');\n\n      if (iframe) {\n        element = iframe;\n      }\n    } // iframe url is not a Vimeo url\n\n\n    if (element.nodeName === 'IFRAME' && !isVimeoUrl(element.getAttribute('src') || '')) {\n      throw new Error('The player element passed isn\u2019t a Vimeo embed.');\n    } // If there is already a player object in the map, return that\n\n\n    if (playerMap.has(element)) {\n      return playerMap.get(element);\n    }\n\n    this._window = element.ownerDocument.defaultView;\n    this.element = element;\n    this.origin = '*';\n    var readyPromise = new npo_src(function (resolve, reject) {\n      _this._onMessage = function (event) {\n        if (!isVimeoUrl(event.origin) || _this.element.contentWindow !== event.source) {\n          return;\n        }\n\n        if (_this.origin === '*') {\n          _this.origin = event.origin;\n        }\n\n        var data = parseMessageData(event.data);\n        var isError = data && data.event === 'error';\n        var isReadyError = isError && data.data && data.data.method === 'ready';\n\n        if (isReadyError) {\n          var error = new Error(data.data.message);\n          error.name = data.data.name;\n          reject(error);\n          return;\n        }\n\n        var isReadyEvent = data && data.event === 'ready';\n        var isPingResponse = data && data.method === 'ping';\n\n        if (isReadyEvent || isPingResponse) {\n          _this.element.setAttribute('data-ready', 'true');\n\n          resolve();\n          return;\n        }\n\n        processData(_this, data);\n      };\n\n      _this._window.addEventListener('message', _this._onMessage);\n\n      if (_this.element.nodeName !== 'IFRAME') {\n        var params = getOEmbedParameters(element, options);\n        var url = getVimeoUrl(params);\n        getOEmbedData(url, params, element).then(function (data) {\n          var iframe = createEmbed(data, element); // Overwrite element with the new iframe,\n          // but store reference to the original element\n\n          _this.element = iframe;\n          _this._originalElement = element;\n          swapCallbacks(element, iframe);\n          playerMap.set(_this.element, _this);\n          return data;\n        }).catch(reject);\n      }\n    }); // Store a copy of this Player in the map\n\n    readyMap.set(this, readyPromise);\n    playerMap.set(this.element, this); // Send a ping to the iframe so the ready promise will be resolved if\n    // the player is already ready.\n\n    if (this.element.nodeName === 'IFRAME') {\n      postMessage(this, 'ping');\n    }\n\n    if (screenfull.isEnabled) {\n      var exitFullscreen = function exitFullscreen() {\n        return screenfull.exit();\n      };\n\n      this.fullscreenchangeHandler = function () {\n        if (screenfull.isFullscreen) {\n          storeCallback(_this, 'event:exitFullscreen', exitFullscreen);\n        } else {\n          removeCallback(_this, 'event:exitFullscreen', exitFullscreen);\n        } // eslint-disable-next-line\n\n\n        _this.ready().then(function () {\n          postMessage(_this, 'fullscreenchange', screenfull.isFullscreen);\n        });\n      };\n\n      screenfull.on('fullscreenchange', this.fullscreenchangeHandler);\n    }\n\n    return this;\n  }\n  /**\n   * Get a promise for a method.\n   *\n   * @param {string} name The API method to call.\n   * @param {Object} [args={}] Arguments to send via postMessage.\n   * @return {Promise}\n   */\n\n\n  _createClass(Player, [{\n    key: \"callMethod\",\n    value: function callMethod(name) {\n      var _this2 = this;\n\n      var args = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n      return new npo_src(function (resolve, reject) {\n        // We are storing the resolve/reject handlers to call later, so we\n        // can\u2019t return here.\n        // eslint-disable-next-line promise/always-return\n        return _this2.ready().then(function () {\n          storeCallback(_this2, name, {\n            resolve: resolve,\n            reject: reject\n          });\n          postMessage(_this2, name, args);\n        }).catch(reject);\n      });\n    }\n    /**\n     * Get a promise for the value of a player property.\n     *\n     * @param {string} name The property name\n     * @return {Promise}\n     */\n\n  }, {\n    key: \"get\",\n    value: function get(name) {\n      var _this3 = this;\n\n      return new npo_src(function (resolve, reject) {\n        name = getMethodName(name, 'get'); // We are storing the resolve/reject handlers to call later, so we\n        // can\u2019t return here.\n        // eslint-disable-next-line promise/always-return\n\n        return _this3.ready().then(function () {\n          storeCallback(_this3, name, {\n            resolve: resolve,\n            reject: reject\n          });\n          postMessage(_this3, name);\n        }).catch(reject);\n      });\n    }\n    /**\n     * Get a promise for setting the value of a player property.\n     *\n     * @param {string} name The API method to call.\n     * @param {mixed} value The value to set.\n     * @return {Promise}\n     */\n\n  }, {\n    key: \"set\",\n    value: function set(name, value) {\n      var _this4 = this;\n\n      return new npo_src(function (resolve, reject) {\n        name = getMethodName(name, 'set');\n\n        if (value === undefined || value === null) {\n          throw new TypeError('There must be a value to set.');\n        } // We are storing the resolve/reject handlers to call later, so we\n        // can\u2019t return here.\n        // eslint-disable-next-line promise/always-return\n\n\n        return _this4.ready().then(function () {\n          storeCallback(_this4, name, {\n            resolve: resolve,\n            reject: reject\n          });\n          postMessage(_this4, name, value);\n        }).catch(reject);\n      });\n    }\n    /**\n     * Add an event listener for the specified event. Will call the\n     * callback with a single parameter, `data`, that contains the data for\n     * that event.\n     *\n     * @param {string} eventName The name of the event.\n     * @param {function(*)} callback The function to call when the event fires.\n     * @return {void}\n     */\n\n  }, {\n    key: \"on\",\n    value: function on(eventName, callback) {\n      if (!eventName) {\n        throw new TypeError('You must pass an event name.');\n      }\n\n      if (!callback) {\n        throw new TypeError('You must pass a callback function.');\n      }\n\n      if (typeof callback !== 'function') {\n        throw new TypeError('The callback must be a function.');\n      }\n\n      var callbacks = getCallbacks(this, \"event:\".concat(eventName));\n\n      if (callbacks.length === 0) {\n        this.callMethod('addEventListener', eventName).catch(function () {// Ignore the error. There will be an error event fired that\n          // will trigger the error callback if they are listening.\n        });\n      }\n\n      storeCallback(this, \"event:\".concat(eventName), callback);\n    }\n    /**\n     * Remove an event listener for the specified event. Will remove all\n     * listeners for that event if a `callback` isn\u2019t passed, or only that\n     * specific callback if it is passed.\n     *\n     * @param {string} eventName The name of the event.\n     * @param {function} [callback] The specific callback to remove.\n     * @return {void}\n     */\n\n  }, {\n    key: \"off\",\n    value: function off(eventName, callback) {\n      if (!eventName) {\n        throw new TypeError('You must pass an event name.');\n      }\n\n      if (callback && typeof callback !== 'function') {\n        throw new TypeError('The callback must be a function.');\n      }\n\n      var lastCallback = removeCallback(this, \"event:\".concat(eventName), callback); // If there are no callbacks left, remove the listener\n\n      if (lastCallback) {\n        this.callMethod('removeEventListener', eventName).catch(function (e) {// Ignore the error. There will be an error event fired that\n          // will trigger the error callback if they are listening.\n        });\n      }\n    }\n    /**\n     * A promise to load a new video.\n     *\n     * @promise LoadVideoPromise\n     * @fulfill {number} The video with this id or url successfully loaded.\n     * @reject {TypeError} The id was not a number.\n     */\n\n    /**\n     * Load a new video into this embed. The promise will be resolved if\n     * the video is successfully loaded, or it will be rejected if it could\n     * not be loaded.\n     *\n     * @param {number|string|object} options The id of the video, the url of the video, or an object with embed options.\n     * @return {LoadVideoPromise}\n     */\n\n  }, {\n    key: \"loadVideo\",\n    value: function loadVideo(options) {\n      return this.callMethod('loadVideo', options);\n    }\n    /**\n     * A promise to perform an action when the Player is ready.\n     *\n     * @todo document errors\n     * @promise LoadVideoPromise\n     * @fulfill {void}\n     */\n\n    /**\n     * Trigger a function when the player iframe has initialized. You do not\n     * need to wait for `ready` to trigger to begin adding event listeners\n     * or calling other methods.\n     *\n     * @return {ReadyPromise}\n     */\n\n  }, {\n    key: \"ready\",\n    value: function ready() {\n      var readyPromise = readyMap.get(this) || new npo_src(function (resolve, reject) {\n        reject(new Error('Unknown player. Probably unloaded.'));\n      });\n      return npo_src.resolve(readyPromise);\n    }\n    /**\n     * A promise to add a cue point to the player.\n     *\n     * @promise AddCuePointPromise\n     * @fulfill {string} The id of the cue point to use for removeCuePoint.\n     * @reject {RangeError} the time was less than 0 or greater than the\n     *         video\u2019s duration.\n     * @reject {UnsupportedError} Cue points are not supported with the current\n     *         player or browser.\n     */\n\n    /**\n     * Add a cue point to the player.\n     *\n     * @param {number} time The time for the cue point.\n     * @param {object} [data] Arbitrary data to be returned with the cue point.\n     * @return {AddCuePointPromise}\n     */\n\n  }, {\n    key: \"addCuePoint\",\n    value: function addCuePoint(time) {\n      var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n      return this.callMethod('addCuePoint', {\n        time: time,\n        data: data\n      });\n    }\n    /**\n     * A promise to remove a cue point from the player.\n     *\n     * @promise AddCuePointPromise\n     * @fulfill {string} The id of the cue point that was removed.\n     * @reject {InvalidCuePoint} The cue point with the specified id was not\n     *         found.\n     * @reject {UnsupportedError} Cue points are not supported with the current\n     *         player or browser.\n     */\n\n    /**\n     * Remove a cue point from the video.\n     *\n     * @param {string} id The id of the cue point to remove.\n     * @return {RemoveCuePointPromise}\n     */\n\n  }, {\n    key: \"removeCuePoint\",\n    value: function removeCuePoint(id) {\n      return this.callMethod('removeCuePoint', id);\n    }\n    /**\n     * A representation of a text track on a video.\n     *\n     * @typedef {Object} VimeoTextTrack\n     * @property {string} language The ISO language code.\n     * @property {string} kind The kind of track it is (captions or subtitles).\n     * @property {string} label The human\u2010readable label for the track.\n     */\n\n    /**\n     * A promise to enable a text track.\n     *\n     * @promise EnableTextTrackPromise\n     * @fulfill {VimeoTextTrack} The text track that was enabled.\n     * @reject {InvalidTrackLanguageError} No track was available with the\n     *         specified language.\n     * @reject {InvalidTrackError} No track was available with the specified\n     *         language and kind.\n     */\n\n    /**\n     * Enable the text track with the specified language, and optionally the\n     * specified kind (captions or subtitles).\n     *\n     * When set via the API, the track language will not change the viewer\u2019s\n     * stored preference.\n     *\n     * @param {string} language The two\u2010letter language code.\n     * @param {string} [kind] The kind of track to enable (captions or subtitles).\n     * @return {EnableTextTrackPromise}\n     */\n\n  }, {\n    key: \"enableTextTrack\",\n    value: function enableTextTrack(language, kind) {\n      if (!language) {\n        throw new TypeError('You must pass a language.');\n      }\n\n      return this.callMethod('enableTextTrack', {\n        language: language,\n        kind: kind\n      });\n    }\n    /**\n     * A promise to disable the active text track.\n     *\n     * @promise DisableTextTrackPromise\n     * @fulfill {void} The track was disabled.\n     */\n\n    /**\n     * Disable the currently-active text track.\n     *\n     * @return {DisableTextTrackPromise}\n     */\n\n  }, {\n    key: \"disableTextTrack\",\n    value: function disableTextTrack() {\n      return this.callMethod('disableTextTrack');\n    }\n    /**\n     * A promise to pause the video.\n     *\n     * @promise PausePromise\n     * @fulfill {void} The video was paused.\n     */\n\n    /**\n     * Pause the video if it\u2019s playing.\n     *\n     * @return {PausePromise}\n     */\n\n  }, {\n    key: \"pause\",\n    value: function pause() {\n      return this.callMethod('pause');\n    }\n    /**\n     * A promise to play the video.\n     *\n     * @promise PlayPromise\n     * @fulfill {void} The video was played.\n     */\n\n    /**\n     * Play the video if it\u2019s paused. **Note:** on iOS and some other\n     * mobile devices, you cannot programmatically trigger play. Once the\n     * viewer has tapped on the play button in the player, however, you\n     * will be able to use this function.\n     *\n     * @return {PlayPromise}\n     */\n\n  }, {\n    key: \"play\",\n    value: function play() {\n      return this.callMethod('play');\n    }\n    /**\n     * Request that the player enters fullscreen.\n     * @return {Promise}\n     */\n\n  }, {\n    key: \"requestFullscreen\",\n    value: function requestFullscreen() {\n      if (screenfull.isEnabled) {\n        return screenfull.request(this.element);\n      }\n\n      return this.callMethod('requestFullscreen');\n    }\n    /**\n     * Request that the player exits fullscreen.\n     * @return {Promise}\n     */\n\n  }, {\n    key: \"exitFullscreen\",\n    value: function exitFullscreen() {\n      if (screenfull.isEnabled) {\n        return screenfull.exit();\n      }\n\n      return this.callMethod('exitFullscreen');\n    }\n    /**\n     * Returns true if the player is currently fullscreen.\n     * @return {Promise}\n     */\n\n  }, {\n    key: \"getFullscreen\",\n    value: function getFullscreen() {\n      if (screenfull.isEnabled) {\n        return npo_src.resolve(screenfull.isFullscreen);\n      }\n\n      return this.get('fullscreen');\n    }\n    /**\n     * Request that the player enters picture-in-picture.\n     * @return {Promise}\n     */\n\n  }, {\n    key: \"requestPictureInPicture\",\n    value: function requestPictureInPicture() {\n      return this.callMethod('requestPictureInPicture');\n    }\n    /**\n     * Request that the player exits picture-in-picture.\n     * @return {Promise}\n     */\n\n  }, {\n    key: \"exitPictureInPicture\",\n    value: function exitPictureInPicture() {\n      return this.callMethod('exitPictureInPicture');\n    }\n    /**\n     * Returns true if the player is currently picture-in-picture.\n     * @return {Promise}\n     */\n\n  }, {\n    key: \"getPictureInPicture\",\n    value: function getPictureInPicture() {\n      return this.get('pictureInPicture');\n    }\n    /**\n     * A promise to prompt the viewer to initiate remote playback.\n     *\n     * @promise RemotePlaybackPromptPromise\n     * @fulfill {void}\n     * @reject {NotFoundError} No remote playback device is available.\n     */\n\n    /**\n     * Request to prompt the user to initiate remote playback.\n     *\n     * @return {RemotePlaybackPromptPromise}\n     */\n\n  }, {\n    key: \"remotePlaybackPrompt\",\n    value: function remotePlaybackPrompt() {\n      return this.callMethod('remotePlaybackPrompt');\n    }\n    /**\n     * A promise to unload the video.\n     *\n     * @promise UnloadPromise\n     * @fulfill {void} The video was unloaded.\n     */\n\n    /**\n     * Return the player to its initial state.\n     *\n     * @return {UnloadPromise}\n     */\n\n  }, {\n    key: \"unload\",\n    value: function unload() {\n      return this.callMethod('unload');\n    }\n    /**\n     * Cleanup the player and remove it from the DOM\n     *\n     * It won't be usable and a new one should be constructed\n     *  in order to do any operations.\n     *\n     * @return {Promise}\n     */\n\n  }, {\n    key: \"destroy\",\n    value: function destroy() {\n      var _this5 = this;\n\n      return new npo_src(function (resolve) {\n        readyMap.delete(_this5);\n        playerMap.delete(_this5.element);\n\n        if (_this5._originalElement) {\n          playerMap.delete(_this5._originalElement);\n\n          _this5._originalElement.removeAttribute('data-vimeo-initialized');\n        }\n\n        if (_this5.element && _this5.element.nodeName === 'IFRAME' && _this5.element.parentNode) {\n          // If we've added an additional wrapper div, remove that from the DOM.\n          // If not, just remove the iframe element.\n          if (_this5.element.parentNode.parentNode && _this5._originalElement && _this5._originalElement !== _this5.element.parentNode) {\n            _this5.element.parentNode.parentNode.removeChild(_this5.element.parentNode);\n          } else {\n            _this5.element.parentNode.removeChild(_this5.element);\n          }\n        } // If the clip is private there is a case where the element stays the\n        // div element. Destroy should reset the div and remove the iframe child.\n\n\n        if (_this5.element && _this5.element.nodeName === 'DIV' && _this5.element.parentNode) {\n          _this5.element.removeAttribute('data-vimeo-initialized');\n\n          var iframe = _this5.element.querySelector('iframe');\n\n          if (iframe && iframe.parentNode) {\n            // If we've added an additional wrapper div, remove that from the DOM.\n            // If not, just remove the iframe element.\n            if (iframe.parentNode.parentNode && _this5._originalElement && _this5._originalElement !== iframe.parentNode) {\n              iframe.parentNode.parentNode.removeChild(iframe.parentNode);\n            } else {\n              iframe.parentNode.removeChild(iframe);\n            }\n          }\n        }\n\n        _this5._window.removeEventListener('message', _this5._onMessage);\n\n        if (screenfull.isEnabled) {\n          screenfull.off('fullscreenchange', _this5.fullscreenchangeHandler);\n        }\n\n        resolve();\n      });\n    }\n    /**\n     * A promise to get the autopause behavior of the video.\n     *\n     * @promise GetAutopausePromise\n     * @fulfill {boolean} Whether autopause is turned on or off.\n     * @reject {UnsupportedError} Autopause is not supported with the current\n     *         player or browser.\n     */\n\n    /**\n     * Get the autopause behavior for this player.\n     *\n     * @return {GetAutopausePromise}\n     */\n\n  }, {\n    key: \"getAutopause\",\n    value: function getAutopause() {\n      return this.get('autopause');\n    }\n    /**\n     * A promise to set the autopause behavior of the video.\n     *\n     * @promise SetAutopausePromise\n     * @fulfill {boolean} Whether autopause is turned on or off.\n     * @reject {UnsupportedError} Autopause is not supported with the current\n     *         player or browser.\n     */\n\n    /**\n     * Enable or disable the autopause behavior of this player.\n     *\n     * By default, when another video is played in the same browser, this\n     * player will automatically pause. Unless you have a specific reason\n     * for doing so, we recommend that you leave autopause set to the\n     * default (`true`).\n     *\n     * @param {boolean} autopause\n     * @return {SetAutopausePromise}\n     */\n\n  }, {\n    key: \"setAutopause\",\n    value: function setAutopause(autopause) {\n      return this.set('autopause', autopause);\n    }\n    /**\n     * A promise to get the buffered property of the video.\n     *\n     * @promise GetBufferedPromise\n     * @fulfill {Array} Buffered Timeranges converted to an Array.\n     */\n\n    /**\n     * Get the buffered property of the video.\n     *\n     * @return {GetBufferedPromise}\n     */\n\n  }, {\n    key: \"getBuffered\",\n    value: function getBuffered() {\n      return this.get('buffered');\n    }\n    /**\n     * @typedef {Object} CameraProperties\n     * @prop {number} props.yaw - Number between 0 and 360.\n     * @prop {number} props.pitch - Number between -90 and 90.\n     * @prop {number} props.roll - Number between -180 and 180.\n     * @prop {number} props.fov - The field of view in degrees.\n     */\n\n    /**\n     * A promise to get the camera properties of the player.\n     *\n     * @promise GetCameraPromise\n     * @fulfill {CameraProperties} The camera properties.\n     */\n\n    /**\n     * For 360\u00B0 videos get the camera properties for this player.\n     *\n     * @return {GetCameraPromise}\n     */\n\n  }, {\n    key: \"getCameraProps\",\n    value: function getCameraProps() {\n      return this.get('cameraProps');\n    }\n    /**\n     * A promise to set the camera properties of the player.\n     *\n     * @promise SetCameraPromise\n     * @fulfill {Object} The camera was successfully set.\n     * @reject {RangeError} The range was out of bounds.\n     */\n\n    /**\n     * For 360\u00B0 videos set the camera properties for this player.\n     *\n     * @param {CameraProperties} camera The camera properties\n     * @return {SetCameraPromise}\n     */\n\n  }, {\n    key: \"setCameraProps\",\n    value: function setCameraProps(camera) {\n      return this.set('cameraProps', camera);\n    }\n    /**\n     * A representation of a chapter.\n     *\n     * @typedef {Object} VimeoChapter\n     * @property {number} startTime The start time of the chapter.\n     * @property {object} title The title of the chapter.\n     * @property {number} index The place in the order of Chapters. Starts at 1.\n     */\n\n    /**\n     * A promise to get chapters for the video.\n     *\n     * @promise GetChaptersPromise\n     * @fulfill {VimeoChapter[]} The chapters for the video.\n     */\n\n    /**\n     * Get an array of all the chapters for the video.\n     *\n     * @return {GetChaptersPromise}\n     */\n\n  }, {\n    key: \"getChapters\",\n    value: function getChapters() {\n      return this.get('chapters');\n    }\n    /**\n     * A promise to get the currently active chapter.\n     *\n     * @promise GetCurrentChaptersPromise\n     * @fulfill {VimeoChapter|undefined} The current chapter for the video.\n     */\n\n    /**\n     * Get the currently active chapter for the video.\n     *\n     * @return {GetCurrentChaptersPromise}\n     */\n\n  }, {\n    key: \"getCurrentChapter\",\n    value: function getCurrentChapter() {\n      return this.get('currentChapter');\n    }\n    /**\n     * A promise to get the color of the player.\n     *\n     * @promise GetColorPromise\n     * @fulfill {string} The hex color of the player.\n     */\n\n    /**\n     * Get the color for this player.\n     *\n     * @return {GetColorPromise}\n     */\n\n  }, {\n    key: \"getColor\",\n    value: function getColor() {\n      return this.get('color');\n    }\n    /**\n     * A promise to set the color of the player.\n     *\n     * @promise SetColorPromise\n     * @fulfill {string} The color was successfully set.\n     * @reject {TypeError} The string was not a valid hex or rgb color.\n     * @reject {ContrastError} The color was set, but the contrast is\n     *         outside of the acceptable range.\n     * @reject {EmbedSettingsError} The owner of the player has chosen to\n     *         use a specific color.\n     */\n\n    /**\n     * Set the color of this player to a hex or rgb string. Setting the\n     * color may fail if the owner of the video has set their embed\n     * preferences to force a specific color.\n     *\n     * @param {string} color The hex or rgb color string to set.\n     * @return {SetColorPromise}\n     */\n\n  }, {\n    key: \"setColor\",\n    value: function setColor(color) {\n      return this.set('color', color);\n    }\n    /**\n     * A representation of a cue point.\n     *\n     * @typedef {Object} VimeoCuePoint\n     * @property {number} time The time of the cue point.\n     * @property {object} data The data passed when adding the cue point.\n     * @property {string} id The unique id for use with removeCuePoint.\n     */\n\n    /**\n     * A promise to get the cue points of a video.\n     *\n     * @promise GetCuePointsPromise\n     * @fulfill {VimeoCuePoint[]} The cue points added to the video.\n     * @reject {UnsupportedError} Cue points are not supported with the current\n     *         player or browser.\n     */\n\n    /**\n     * Get an array of the cue points added to the video.\n     *\n     * @return {GetCuePointsPromise}\n     */\n\n  }, {\n    key: \"getCuePoints\",\n    value: function getCuePoints() {\n      return this.get('cuePoints');\n    }\n    /**\n     * A promise to get the current time of the video.\n     *\n     * @promise GetCurrentTimePromise\n     * @fulfill {number} The current time in seconds.\n     */\n\n    /**\n     * Get the current playback position in seconds.\n     *\n     * @return {GetCurrentTimePromise}\n     */\n\n  }, {\n    key: \"getCurrentTime\",\n    value: function getCurrentTime() {\n      return this.get('currentTime');\n    }\n    /**\n     * A promise to set the current time of the video.\n     *\n     * @promise SetCurrentTimePromise\n     * @fulfill {number} The actual current time that was set.\n     * @reject {RangeError} the time was less than 0 or greater than the\n     *         video\u2019s duration.\n     */\n\n    /**\n     * Set the current playback position in seconds. If the player was\n     * paused, it will remain paused. Likewise, if the player was playing,\n     * it will resume playing once the video has buffered.\n     *\n     * You can provide an accurate time and the player will attempt to seek\n     * to as close to that time as possible. The exact time will be the\n     * fulfilled value of the promise.\n     *\n     * @param {number} currentTime\n     * @return {SetCurrentTimePromise}\n     */\n\n  }, {\n    key: \"setCurrentTime\",\n    value: function setCurrentTime(currentTime) {\n      return this.set('currentTime', currentTime);\n    }\n    /**\n     * A promise to get the duration of the video.\n     *\n     * @promise GetDurationPromise\n     * @fulfill {number} The duration in seconds.\n     */\n\n    /**\n     * Get the duration of the video in seconds. It will be rounded to the\n     * nearest second before playback begins, and to the nearest thousandth\n     * of a second after playback begins.\n     *\n     * @return {GetDurationPromise}\n     */\n\n  }, {\n    key: \"getDuration\",\n    value: function getDuration() {\n      return this.get('duration');\n    }\n    /**\n     * A promise to get the ended state of the video.\n     *\n     * @promise GetEndedPromise\n     * @fulfill {boolean} Whether or not the video has ended.\n     */\n\n    /**\n     * Get the ended state of the video. The video has ended if\n     * `currentTime === duration`.\n     *\n     * @return {GetEndedPromise}\n     */\n\n  }, {\n    key: \"getEnded\",\n    value: function getEnded() {\n      return this.get('ended');\n    }\n    /**\n     * A promise to get the loop state of the player.\n     *\n     * @promise GetLoopPromise\n     * @fulfill {boolean} Whether or not the player is set to loop.\n     */\n\n    /**\n     * Get the loop state of the player.\n     *\n     * @return {GetLoopPromise}\n     */\n\n  }, {\n    key: \"getLoop\",\n    value: function getLoop() {\n      return this.get('loop');\n    }\n    /**\n     * A promise to set the loop state of the player.\n     *\n     * @promise SetLoopPromise\n     * @fulfill {boolean} The loop state that was set.\n     */\n\n    /**\n     * Set the loop state of the player. When set to `true`, the player\n     * will start over immediately once playback ends.\n     *\n     * @param {boolean} loop\n     * @return {SetLoopPromise}\n     */\n\n  }, {\n    key: \"setLoop\",\n    value: function setLoop(loop) {\n      return this.set('loop', loop);\n    }\n    /**\n     * A promise to set the muted state of the player.\n     *\n     * @promise SetMutedPromise\n     * @fulfill {boolean} The muted state that was set.\n     */\n\n    /**\n     * Set the muted state of the player. When set to `true`, the player\n     * volume will be muted.\n     *\n     * @param {boolean} muted\n     * @return {SetMutedPromise}\n     */\n\n  }, {\n    key: \"setMuted\",\n    value: function setMuted(muted) {\n      return this.set('muted', muted);\n    }\n    /**\n     * A promise to get the muted state of the player.\n     *\n     * @promise GetMutedPromise\n     * @fulfill {boolean} Whether or not the player is muted.\n     */\n\n    /**\n     * Get the muted state of the player.\n     *\n     * @return {GetMutedPromise}\n     */\n\n  }, {\n    key: \"getMuted\",\n    value: function getMuted() {\n      return this.get('muted');\n    }\n    /**\n     * A promise to get the paused state of the player.\n     *\n     * @promise GetLoopPromise\n     * @fulfill {boolean} Whether or not the video is paused.\n     */\n\n    /**\n     * Get the paused state of the player.\n     *\n     * @return {GetLoopPromise}\n     */\n\n  }, {\n    key: \"getPaused\",\n    value: function getPaused() {\n      return this.get('paused');\n    }\n    /**\n     * A promise to get the playback rate of the player.\n     *\n     * @promise GetPlaybackRatePromise\n     * @fulfill {number} The playback rate of the player on a scale from 0 to 2.\n     */\n\n    /**\n     * Get the playback rate of the player on a scale from `0` to `2`.\n     *\n     * @return {GetPlaybackRatePromise}\n     */\n\n  }, {\n    key: \"getPlaybackRate\",\n    value: function getPlaybackRate() {\n      return this.get('playbackRate');\n    }\n    /**\n     * A promise to set the playbackrate of the player.\n     *\n     * @promise SetPlaybackRatePromise\n     * @fulfill {number} The playback rate was set.\n     * @reject {RangeError} The playback rate was less than 0 or greater than 2.\n     */\n\n    /**\n     * Set the playback rate of the player on a scale from `0` to `2`. When set\n     * via the API, the playback rate will not be synchronized to other\n     * players or stored as the viewer's preference.\n     *\n     * @param {number} playbackRate\n     * @return {SetPlaybackRatePromise}\n     */\n\n  }, {\n    key: \"setPlaybackRate\",\n    value: function setPlaybackRate(playbackRate) {\n      return this.set('playbackRate', playbackRate);\n    }\n    /**\n     * A promise to get the played property of the video.\n     *\n     * @promise GetPlayedPromise\n     * @fulfill {Array} Played Timeranges converted to an Array.\n     */\n\n    /**\n     * Get the played property of the video.\n     *\n     * @return {GetPlayedPromise}\n     */\n\n  }, {\n    key: \"getPlayed\",\n    value: function getPlayed() {\n      return this.get('played');\n    }\n    /**\n     * A promise to get the qualities available of the current video.\n     *\n     * @promise GetQualitiesPromise\n     * @fulfill {Array} The qualities of the video.\n     */\n\n    /**\n     * Get the qualities of the current video.\n     *\n     * @return {GetQualitiesPromise}\n     */\n\n  }, {\n    key: \"getQualities\",\n    value: function getQualities() {\n      return this.get('qualities');\n    }\n    /**\n     * A promise to get the current set quality of the video.\n     *\n     * @promise GetQualityPromise\n     * @fulfill {string} The current set quality.\n     */\n\n    /**\n     * Get the current set quality of the video.\n     *\n     * @return {GetQualityPromise}\n     */\n\n  }, {\n    key: \"getQuality\",\n    value: function getQuality() {\n      return this.get('quality');\n    }\n    /**\n     * A promise to set the video quality.\n     *\n     * @promise SetQualityPromise\n     * @fulfill {number} The quality was set.\n     * @reject {RangeError} The quality is not available.\n     */\n\n    /**\n     * Set a video quality.\n     *\n     * @param {string} quality\n     * @return {SetQualityPromise}\n     */\n\n  }, {\n    key: \"setQuality\",\n    value: function setQuality(quality) {\n      return this.set('quality', quality);\n    }\n    /**\n     * A promise to get the remote playback availability.\n     *\n     * @promise RemotePlaybackAvailabilityPromise\n     * @fulfill {boolean} Whether remote playback is available.\n     */\n\n    /**\n     * Get the availability of remote playback.\n     *\n     * @return {RemotePlaybackAvailabilityPromise}\n     */\n\n  }, {\n    key: \"getRemotePlaybackAvailability\",\n    value: function getRemotePlaybackAvailability() {\n      return this.get('remotePlaybackAvailability');\n    }\n    /**\n     * A promise to get the current remote playback state.\n     *\n     * @promise RemotePlaybackStatePromise\n     * @fulfill {string} The state of the remote playback: connecting, connected, or disconnected.\n     */\n\n    /**\n     * Get the current remote playback state.\n     *\n     * @return {RemotePlaybackStatePromise}\n     */\n\n  }, {\n    key: \"getRemotePlaybackState\",\n    value: function getRemotePlaybackState() {\n      return this.get('remotePlaybackState');\n    }\n    /**\n     * A promise to get the seekable property of the video.\n     *\n     * @promise GetSeekablePromise\n     * @fulfill {Array} Seekable Timeranges converted to an Array.\n     */\n\n    /**\n     * Get the seekable property of the video.\n     *\n     * @return {GetSeekablePromise}\n     */\n\n  }, {\n    key: \"getSeekable\",\n    value: function getSeekable() {\n      return this.get('seekable');\n    }\n    /**\n     * A promise to get the seeking property of the player.\n     *\n     * @promise GetSeekingPromise\n     * @fulfill {boolean} Whether or not the player is currently seeking.\n     */\n\n    /**\n     * Get if the player is currently seeking.\n     *\n     * @return {GetSeekingPromise}\n     */\n\n  }, {\n    key: \"getSeeking\",\n    value: function getSeeking() {\n      return this.get('seeking');\n    }\n    /**\n     * A promise to get the text tracks of a video.\n     *\n     * @promise GetTextTracksPromise\n     * @fulfill {VimeoTextTrack[]} The text tracks associated with the video.\n     */\n\n    /**\n     * Get an array of the text tracks that exist for the video.\n     *\n     * @return {GetTextTracksPromise}\n     */\n\n  }, {\n    key: \"getTextTracks\",\n    value: function getTextTracks() {\n      return this.get('textTracks');\n    }\n    /**\n     * A promise to get the embed code for the video.\n     *\n     * @promise GetVideoEmbedCodePromise\n     * @fulfill {string} The `<iframe>` embed code for the video.\n     */\n\n    /**\n     * Get the `<iframe>` embed code for the video.\n     *\n     * @return {GetVideoEmbedCodePromise}\n     */\n\n  }, {\n    key: \"getVideoEmbedCode\",\n    value: function getVideoEmbedCode() {\n      return this.get('videoEmbedCode');\n    }\n    /**\n     * A promise to get the id of the video.\n     *\n     * @promise GetVideoIdPromise\n     * @fulfill {number} The id of the video.\n     */\n\n    /**\n     * Get the id of the video.\n     *\n     * @return {GetVideoIdPromise}\n     */\n\n  }, {\n    key: \"getVideoId\",\n    value: function getVideoId() {\n      return this.get('videoId');\n    }\n    /**\n     * A promise to get the title of the video.\n     *\n     * @promise GetVideoTitlePromise\n     * @fulfill {number} The title of the video.\n     */\n\n    /**\n     * Get the title of the video.\n     *\n     * @return {GetVideoTitlePromise}\n     */\n\n  }, {\n    key: \"getVideoTitle\",\n    value: function getVideoTitle() {\n      return this.get('videoTitle');\n    }\n    /**\n     * A promise to get the native width of the video.\n     *\n     * @promise GetVideoWidthPromise\n     * @fulfill {number} The native width of the video.\n     */\n\n    /**\n     * Get the native width of the currently\u2010playing video. The width of\n     * the highest\u2010resolution available will be used before playback begins.\n     *\n     * @return {GetVideoWidthPromise}\n     */\n\n  }, {\n    key: \"getVideoWidth\",\n    value: function getVideoWidth() {\n      return this.get('videoWidth');\n    }\n    /**\n     * A promise to get the native height of the video.\n     *\n     * @promise GetVideoHeightPromise\n     * @fulfill {number} The native height of the video.\n     */\n\n    /**\n     * Get the native height of the currently\u2010playing video. The height of\n     * the highest\u2010resolution available will be used before playback begins.\n     *\n     * @return {GetVideoHeightPromise}\n     */\n\n  }, {\n    key: \"getVideoHeight\",\n    value: function getVideoHeight() {\n      return this.get('videoHeight');\n    }\n    /**\n     * A promise to get the vimeo.com url for the video.\n     *\n     * @promise GetVideoUrlPromise\n     * @fulfill {number} The vimeo.com url for the video.\n     * @reject {PrivacyError} The url isn\u2019t available because of the video\u2019s privacy setting.\n     */\n\n    /**\n     * Get the vimeo.com url for the video.\n     *\n     * @return {GetVideoUrlPromise}\n     */\n\n  }, {\n    key: \"getVideoUrl\",\n    value: function getVideoUrl() {\n      return this.get('videoUrl');\n    }\n    /**\n     * A promise to get the volume level of the player.\n     *\n     * @promise GetVolumePromise\n     * @fulfill {number} The volume level of the player on a scale from 0 to 1.\n     */\n\n    /**\n     * Get the current volume level of the player on a scale from `0` to `1`.\n     *\n     * Most mobile devices do not support an independent volume from the\n     * system volume. In those cases, this method will always return `1`.\n     *\n     * @return {GetVolumePromise}\n     */\n\n  }, {\n    key: \"getVolume\",\n    value: function getVolume() {\n      return this.get('volume');\n    }\n    /**\n     * A promise to set the volume level of the player.\n     *\n     * @promise SetVolumePromise\n     * @fulfill {number} The volume was set.\n     * @reject {RangeError} The volume was less than 0 or greater than 1.\n     */\n\n    /**\n     * Set the volume of the player on a scale from `0` to `1`. When set\n     * via the API, the volume level will not be synchronized to other\n     * players or stored as the viewer\u2019s preference.\n     *\n     * Most mobile devices do not support setting the volume. An error will\n     * *not* be triggered in that situation.\n     *\n     * @param {number} volume\n     * @return {SetVolumePromise}\n     */\n\n  }, {\n    key: \"setVolume\",\n    value: function setVolume(volume) {\n      return this.set('volume', volume);\n    }\n  }]);\n\n  return Player;\n}(); // Setup embed only if this is not a node environment\n\n\nif (!isNode) {\n  screenfull = initializeScreenfull();\n  initializeEmbeds();\n  resizeEmbeds();\n  initAppendVideoMetadata();\n  checkUrlTimeParam();\n}\n\nexport default Player;\n", "import Player from '@vimeo/player'\nconst LOOR_BRAND_COLOR = '#F5C518'\n\nfunction throttle(func, duration) {\n  let shouldWait = false\n\n  return function (...args) {\n    if (!shouldWait) {\n      func.apply(this, args)\n      shouldWait = true\n\n      setTimeout(function () {\n        shouldWait = false\n      }, duration)\n    }\n  }\n}\n\nexport default ({\n  video_id,\n  watch_progress = false,\n  user_id,\n  project_id,\n  episode_number,\n}) => ({\n  video_id,\n  player: null,\n  watch_progress,\n  playerTracker: null,\n  user_id,\n  project_id,\n  episode_number,\n  csrf: '',\n  init() {\n    this.csrf = document.querySelector('meta[name=csrf-token]').content\n    const embed = document.getElementById('vimeo-player')\n    const player = new Player('vimeo-player', {\n      id: this.video_id,\n      // responsive: true,\n      color: LOOR_BRAND_COLOR,\n      autoplay: true,\n      byline: false,\n      portrait: false,\n      title: false,\n    })\n    this.player = player\n\n    // Expose this single Player instance so sibling components (e.g. the credits\n    // roll) consume it instead of constructing a second Player on the same iframe\n    // (which would register a duplicate, never-torn-down window message listener).\n    // The credits roll listens for the plain DOM `movie:ended` event below.\n    if (embed) {\n      embed.__loorPlayer = player\n      let endedFired = false\n      const fireEnded = () => {\n        if (endedFired) return\n        endedFired = true\n        embed.dispatchEvent(new CustomEvent('movie:ended', { bubbles: true }))\n      }\n      player.on('ended', fireEnded)\n\n      // Fallback for platforms/casting that drop `ended`: attach a near-end\n      // timeupdate check only for the last few seconds (not the whole movie),\n      // and only fire on genuine forward progress so scrubbing to the end to\n      // *skip* doesn't roll credits over a still-playing film.\n      player\n        .getDuration()\n        .then((duration) => {\n          if (!duration) return\n          let last = 0\n          player.on('timeupdate', ({ seconds }) => {\n            const nearEnd = seconds >= duration - 1.5\n            const movingForward = seconds >= last\n            last = seconds\n            if (nearEnd && movingForward) fireEnded()\n          })\n        })\n        .catch(() => {\n          // No duration available: rely on the `ended` event alone.\n        })\n\n      // Scrubbing back or resuming play clears the post-movie credits roll\n      // (credits_sync.js listens), so the viewer is never trapped on the credits\n      // with the Vimeo controls covered.\n      const fireResumed = () =>\n        embed.dispatchEvent(new CustomEvent('movie:resumed', { bubbles: true }))\n      player.on('play', fireResumed)\n      player.on('seeked', fireResumed)\n    }\n\n    // Set the branding color\n    player.setColor(LOOR_BRAND_COLOR)\n\n    // Resume where the viewer was. An explicit ?t= (from the games' \"Back to the\n    // movie\") wins \u2014 land exactly on the paused frame and stay paused; otherwise\n    // use the server-persisted watch progress.\n    const resumeAt = Number(new URLSearchParams(window.location.search).get('t'))\n    if (!Number.isNaN(resumeAt) && resumeAt > 0) {\n      player\n        .setCurrentTime(resumeAt)\n        .then(() => player.pause())\n        .catch(() => {})\n    } else if (watch_progress) {\n      player.setCurrentTime(watch_progress)\n    }\n\n    // \"Want to play a game?\" \u2014 button over the paused movie after 10s.\n    this.setupGamePrompt(player)\n\n    // start tracking watch progress\n    // NOTE: play/pause events don't fire while casting, but timeupdate does and it doesn't fire while the video is paused\n    player.on(\n      'timeupdate',\n      throttle(({ seconds }) => {\n        // console.log('timeupdate', seconds)\n        this.setServerWatchTime(seconds)\n      }, 5000)\n    )\n  },\n  setupGamePrompt(player) {\n    const prompt = document.getElementById('game-prompt')\n    const link = document.getElementById('game-prompt-link')\n    if (!prompt || !link) return\n\n    let timer = null\n\n    const hide = () => {\n      if (timer) {\n        clearTimeout(timer)\n        timer = null\n      }\n      prompt.classList.add('hidden')\n    }\n\n    const show = () => {\n      player\n        .getCurrentTime()\n        .then((seconds) => {\n          const params = new URLSearchParams({\n            return_to: `${window.location.pathname}?t=${Math.floor(seconds)}`,\n          })\n          if (prompt.dataset.projectId) params.set('sp', prompt.dataset.projectId)\n          if (prompt.dataset.episodeId) params.set('se', prompt.dataset.episodeId)\n          link.href = `/popcorn/tv?${params.toString()}`\n        })\n        .catch(() => {})\n      prompt.classList.remove('hidden')\n    }\n\n    player.on('pause', () => {\n      if (timer) clearTimeout(timer)\n      timer = setTimeout(show, 10000)\n    })\n    player.on('play', hide)\n  },\n  setServerWatchTime(seconds) {\n    const watchBody = JSON.stringify({\n      user_id: this.user_id,\n      project_id: this.project_id,\n      episode_number: this.episode_number,\n      watch_progress: Math.floor(seconds),\n    })\n    fetch('/events/watch', {\n      method: 'POST',\n      body: watchBody,\n      headers: {\n        'Content-Type': 'application/json',\n        'X-CSRF-Token': this.csrf,\n      },\n    })\n  },\n})\n", "// see https://tools.ietf.org/html/rfc1808\n\n(function (root) {\n  var URL_REGEX =\n    /^(?=((?:[a-zA-Z0-9+\\-.]+:)?))\\1(?=((?:\\/\\/[^\\/?#]*)?))\\2(?=((?:(?:[^?#\\/]*\\/)*[^;?#\\/]*)?))\\3((?:;[^?#]*)?)(\\?[^#]*)?(#[^]*)?$/;\n  var FIRST_SEGMENT_REGEX = /^(?=([^\\/?#]*))\\1([^]*)$/;\n  var SLASH_DOT_REGEX = /(?:\\/|^)\\.(?=\\/)/g;\n  var SLASH_DOT_DOT_REGEX = /(?:\\/|^)\\.\\.\\/(?!\\.\\.\\/)[^\\/]*(?=\\/)/g;\n\n  var URLToolkit = {\n    // If opts.alwaysNormalize is true then the path will always be normalized even when it starts with / or //\n    // E.g\n    // With opts.alwaysNormalize = false (default, spec compliant)\n    // http://a.com/b/cd + /e/f/../g => http://a.com/e/f/../g\n    // With opts.alwaysNormalize = true (not spec compliant)\n    // http://a.com/b/cd + /e/f/../g => http://a.com/e/g\n    buildAbsoluteURL: function (baseURL, relativeURL, opts) {\n      opts = opts || {};\n      // remove any remaining space and CRLF\n      baseURL = baseURL.trim();\n      relativeURL = relativeURL.trim();\n      if (!relativeURL) {\n        // 2a) If the embedded URL is entirely empty, it inherits the\n        // entire base URL (i.e., is set equal to the base URL)\n        // and we are done.\n        if (!opts.alwaysNormalize) {\n          return baseURL;\n        }\n        var basePartsForNormalise = URLToolkit.parseURL(baseURL);\n        if (!basePartsForNormalise) {\n          throw new Error('Error trying to parse base URL.');\n        }\n        basePartsForNormalise.path = URLToolkit.normalizePath(\n          basePartsForNormalise.path\n        );\n        return URLToolkit.buildURLFromParts(basePartsForNormalise);\n      }\n      var relativeParts = URLToolkit.parseURL(relativeURL);\n      if (!relativeParts) {\n        throw new Error('Error trying to parse relative URL.');\n      }\n      if (relativeParts.scheme) {\n        // 2b) If the embedded URL starts with a scheme name, it is\n        // interpreted as an absolute URL and we are done.\n        if (!opts.alwaysNormalize) {\n          return relativeURL;\n        }\n        relativeParts.path = URLToolkit.normalizePath(relativeParts.path);\n        return URLToolkit.buildURLFromParts(relativeParts);\n      }\n      var baseParts = URLToolkit.parseURL(baseURL);\n      if (!baseParts) {\n        throw new Error('Error trying to parse base URL.');\n      }\n      if (!baseParts.netLoc && baseParts.path && baseParts.path[0] !== '/') {\n        // If netLoc missing and path doesn't start with '/', assume everthing before the first '/' is the netLoc\n        // This causes 'example.com/a' to be handled as '//example.com/a' instead of '/example.com/a'\n        var pathParts = FIRST_SEGMENT_REGEX.exec(baseParts.path);\n        baseParts.netLoc = pathParts[1];\n        baseParts.path = pathParts[2];\n      }\n      if (baseParts.netLoc && !baseParts.path) {\n        baseParts.path = '/';\n      }\n      var builtParts = {\n        // 2c) Otherwise, the embedded URL inherits the scheme of\n        // the base URL.\n        scheme: baseParts.scheme,\n        netLoc: relativeParts.netLoc,\n        path: null,\n        params: relativeParts.params,\n        query: relativeParts.query,\n        fragment: relativeParts.fragment,\n      };\n      if (!relativeParts.netLoc) {\n        // 3) If the embedded URL's <net_loc> is non-empty, we skip to\n        // Step 7.  Otherwise, the embedded URL inherits the <net_loc>\n        // (if any) of the base URL.\n        builtParts.netLoc = baseParts.netLoc;\n        // 4) If the embedded URL path is preceded by a slash \"/\", the\n        // path is not relative and we skip to Step 7.\n        if (relativeParts.path[0] !== '/') {\n          if (!relativeParts.path) {\n            // 5) If the embedded URL path is empty (and not preceded by a\n            // slash), then the embedded URL inherits the base URL path\n            builtParts.path = baseParts.path;\n            // 5a) if the embedded URL's <params> is non-empty, we skip to\n            // step 7; otherwise, it inherits the <params> of the base\n            // URL (if any) and\n            if (!relativeParts.params) {\n              builtParts.params = baseParts.params;\n              // 5b) if the embedded URL's <query> is non-empty, we skip to\n              // step 7; otherwise, it inherits the <query> of the base\n              // URL (if any) and we skip to step 7.\n              if (!relativeParts.query) {\n                builtParts.query = baseParts.query;\n              }\n            }\n          } else {\n            // 6) The last segment of the base URL's path (anything\n            // following the rightmost slash \"/\", or the entire path if no\n            // slash is present) is removed and the embedded URL's path is\n            // appended in its place.\n            var baseURLPath = baseParts.path;\n            var newPath =\n              baseURLPath.substring(0, baseURLPath.lastIndexOf('/') + 1) +\n              relativeParts.path;\n            builtParts.path = URLToolkit.normalizePath(newPath);\n          }\n        }\n      }\n      if (builtParts.path === null) {\n        builtParts.path = opts.alwaysNormalize\n          ? URLToolkit.normalizePath(relativeParts.path)\n          : relativeParts.path;\n      }\n      return URLToolkit.buildURLFromParts(builtParts);\n    },\n    parseURL: function (url) {\n      var parts = URL_REGEX.exec(url);\n      if (!parts) {\n        return null;\n      }\n      return {\n        scheme: parts[1] || '',\n        netLoc: parts[2] || '',\n        path: parts[3] || '',\n        params: parts[4] || '',\n        query: parts[5] || '',\n        fragment: parts[6] || '',\n      };\n    },\n    normalizePath: function (path) {\n      // The following operations are\n      // then applied, in order, to the new path:\n      // 6a) All occurrences of \"./\", where \".\" is a complete path\n      // segment, are removed.\n      // 6b) If the path ends with \".\" as a complete path segment,\n      // that \".\" is removed.\n      path = path.split('').reverse().join('').replace(SLASH_DOT_REGEX, '');\n      // 6c) All occurrences of \"<segment>/../\", where <segment> is a\n      // complete path segment not equal to \"..\", are removed.\n      // Removal of these path segments is performed iteratively,\n      // removing the leftmost matching pattern on each iteration,\n      // until no matching pattern remains.\n      // 6d) If the path ends with \"<segment>/..\", where <segment> is a\n      // complete path segment not equal to \"..\", that\n      // \"<segment>/..\" is removed.\n      while (\n        path.length !== (path = path.replace(SLASH_DOT_DOT_REGEX, '')).length\n      ) {}\n      return path.split('').reverse().join('');\n    },\n    buildURLFromParts: function (parts) {\n      return (\n        parts.scheme +\n        parts.netLoc +\n        parts.path +\n        parts.params +\n        parts.query +\n        parts.fragment\n      );\n    },\n  };\n\n  if (typeof exports === 'object' && typeof module === 'object')\n    module.exports = URLToolkit;\n  else if (typeof define === 'function' && define.amd)\n    define([], function () {\n      return URLToolkit;\n    });\n  else if (typeof exports === 'object') exports['URLToolkit'] = URLToolkit;\n  else root['URLToolkit'] = URLToolkit;\n})(this);\n", "// https://caniuse.com/mdn-javascript_builtins_number_isfinite\nexport const isFiniteNumber =\n  Number.isFinite ||\n  function (value) {\n    return typeof value === 'number' && isFinite(value);\n  };\n\n// https://caniuse.com/mdn-javascript_builtins_number_issafeinteger\nexport const isSafeInteger =\n  Number.isSafeInteger ||\n  function (value) {\n    return typeof value === 'number' && Math.abs(value) <= MAX_SAFE_INTEGER;\n  };\n\nexport const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991;\n", "import {\n  ManifestLoadedData,\n  ManifestLoadingData,\n  MediaAttachedData,\n  MediaAttachingData,\n  LevelLoadingData,\n  LevelLoadedData,\n  ManifestParsedData,\n  LevelUpdatedData,\n  LevelsUpdatedData,\n  FragParsingUserdataData,\n  FragDecryptedData,\n  FragLoadedData,\n  InitPTSFoundData,\n  CuesParsedData,\n  SubtitleFragProcessedData,\n  NonNativeTextTracksData,\n  FragLoadingData,\n  AudioTrackLoadedData,\n  SubtitleTrackLoadedData,\n  ErrorData,\n  AudioTrackSwitchingData,\n  AudioTrackSwitchedData,\n  KeyLoadedData,\n  KeyLoadingData,\n  SubtitleTrackSwitchData,\n  SubtitleTracksUpdatedData,\n  LevelSwitchedData,\n  FragChangedData,\n  BufferAppendingData,\n  BufferCodecsData,\n  FragParsingMetadataData,\n  FragParsingInitSegmentData,\n  FragBufferedData,\n  BufferFlushingData,\n  BufferEOSData,\n  LevelSwitchingData,\n  MaxAutoLevelUpdatedData,\n  FPSDropLevelCappingData,\n  FPSDropData,\n  BufferCreatedData,\n  BufferAppendedData,\n  LevelPTSUpdatedData,\n  FragParsedData,\n  AudioTracksUpdatedData,\n  FragLoadEmergencyAbortedData,\n  BackBufferData,\n  LiveBackBufferData,\n  TrackLoadingData,\n  BufferFlushedData,\n  SteeringManifestLoadedData,\n} from './types/events';\n\nexport enum Events {\n  // Fired before MediaSource is attaching to media element\n  MEDIA_ATTACHING = 'hlsMediaAttaching',\n  // Fired when MediaSource has been successfully attached to media element\n  MEDIA_ATTACHED = 'hlsMediaAttached',\n  // Fired before detaching MediaSource from media element\n  MEDIA_DETACHING = 'hlsMediaDetaching',\n  // Fired when MediaSource has been detached from media element\n  MEDIA_DETACHED = 'hlsMediaDetached',\n  // Fired when the buffer is going to be reset\n  BUFFER_RESET = 'hlsBufferReset',\n  // Fired when we know about the codecs that we need buffers for to push into - data: {tracks : { container, codec, levelCodec, initSegment, metadata }}\n  BUFFER_CODECS = 'hlsBufferCodecs',\n  // fired when sourcebuffers have been created - data: { tracks : tracks }\n  BUFFER_CREATED = 'hlsBufferCreated',\n  // fired when we append a segment to the buffer - data: { segment: segment object }\n  BUFFER_APPENDING = 'hlsBufferAppending',\n  // fired when we are done with appending a media segment to the buffer - data : { parent : segment parent that triggered BUFFER_APPENDING, pending : nb of segments waiting for appending for this segment parent}\n  BUFFER_APPENDED = 'hlsBufferAppended',\n  // fired when the stream is finished and we want to notify the media buffer that there will be no more data - data: { }\n  BUFFER_EOS = 'hlsBufferEos',\n  // fired when the media buffer should be flushed - data { startOffset, endOffset }\n  BUFFER_FLUSHING = 'hlsBufferFlushing',\n  // fired when the media buffer has been flushed - data: { }\n  BUFFER_FLUSHED = 'hlsBufferFlushed',\n  // fired to signal that a manifest loading starts - data: { url : manifestURL}\n  MANIFEST_LOADING = 'hlsManifestLoading',\n  // fired after manifest has been loaded - data: { levels : [available quality levels], audioTracks : [ available audio tracks ], url : manifestURL, stats : LoaderStats }\n  MANIFEST_LOADED = 'hlsManifestLoaded',\n  // fired after manifest has been parsed - data: { levels : [available quality levels], firstLevel : index of first quality level appearing in Manifest}\n  MANIFEST_PARSED = 'hlsManifestParsed',\n  // fired when a level switch is requested - data: { level : id of new level }\n  LEVEL_SWITCHING = 'hlsLevelSwitching',\n  // fired when a level switch is effective - data: { level : id of new level }\n  LEVEL_SWITCHED = 'hlsLevelSwitched',\n  // fired when a level playlist loading starts - data: { url : level URL, level : id of level being loaded}\n  LEVEL_LOADING = 'hlsLevelLoading',\n  // fired when a level playlist loading finishes - data: { details : levelDetails object, level : id of loaded level, stats : LoaderStats }\n  LEVEL_LOADED = 'hlsLevelLoaded',\n  // fired when a level's details have been updated based on previous details, after it has been loaded - data: { details : levelDetails object, level : id of updated level }\n  LEVEL_UPDATED = 'hlsLevelUpdated',\n  // fired when a level's PTS information has been updated after parsing a fragment - data: { details : levelDetails object, level : id of updated level, drift: PTS drift observed when parsing last fragment }\n  LEVEL_PTS_UPDATED = 'hlsLevelPtsUpdated',\n  // fired to notify that levels have changed after removing a level - data: { levels : [available quality levels] }\n  LEVELS_UPDATED = 'hlsLevelsUpdated',\n  // fired to notify that audio track lists has been updated - data: { audioTracks : audioTracks }\n  AUDIO_TRACKS_UPDATED = 'hlsAudioTracksUpdated',\n  // fired when an audio track switching is requested - data: { id : audio track id }\n  AUDIO_TRACK_SWITCHING = 'hlsAudioTrackSwitching',\n  // fired when an audio track switch actually occurs - data: { id : audio track id }\n  AUDIO_TRACK_SWITCHED = 'hlsAudioTrackSwitched',\n  // fired when an audio track loading starts - data: { url : audio track URL, id : audio track id }\n  AUDIO_TRACK_LOADING = 'hlsAudioTrackLoading',\n  // fired when an audio track loading finishes - data: { details : levelDetails object, id : audio track id, stats : LoaderStats }\n  AUDIO_TRACK_LOADED = 'hlsAudioTrackLoaded',\n  // fired to notify that subtitle track lists has been updated - data: { subtitleTracks : subtitleTracks }\n  SUBTITLE_TRACKS_UPDATED = 'hlsSubtitleTracksUpdated',\n  // fired to notify that subtitle tracks were cleared as a result of stopping the media\n  SUBTITLE_TRACKS_CLEARED = 'hlsSubtitleTracksCleared',\n  // fired when an subtitle track switch occurs - data: { id : subtitle track id }\n  SUBTITLE_TRACK_SWITCH = 'hlsSubtitleTrackSwitch',\n  // fired when a subtitle track loading starts - data: { url : subtitle track URL, id : subtitle track id }\n  SUBTITLE_TRACK_LOADING = 'hlsSubtitleTrackLoading',\n  // fired when a subtitle track loading finishes - data: { details : levelDetails object, id : subtitle track id, stats : LoaderStats }\n  SUBTITLE_TRACK_LOADED = 'hlsSubtitleTrackLoaded',\n  // fired when a subtitle fragment has been processed - data: { success : boolean, frag : the processed frag }\n  SUBTITLE_FRAG_PROCESSED = 'hlsSubtitleFragProcessed',\n  // fired when a set of VTTCues to be managed externally has been parsed - data: { type: string, track: string, cues: [ VTTCue ] }\n  CUES_PARSED = 'hlsCuesParsed',\n  // fired when a text track to be managed externally is found - data: { tracks: [ { label: string, kind: string, default: boolean } ] }\n  NON_NATIVE_TEXT_TRACKS_FOUND = 'hlsNonNativeTextTracksFound',\n  // fired when the first timestamp is found - data: { id : demuxer id, initPTS: initPTS, timescale: timescale, frag : fragment object }\n  INIT_PTS_FOUND = 'hlsInitPtsFound',\n  // fired when a fragment loading starts - data: { frag : fragment object }\n  FRAG_LOADING = 'hlsFragLoading',\n  // fired when a fragment loading is progressing - data: { frag : fragment object, { trequest, tfirst, loaded } }\n  // FRAG_LOAD_PROGRESS = 'hlsFragLoadProgress',\n  // Identifier for fragment load aborting for emergency switch down - data: { frag : fragment object }\n  FRAG_LOAD_EMERGENCY_ABORTED = 'hlsFragLoadEmergencyAborted',\n  // fired when a fragment loading is completed - data: { frag : fragment object, payload : fragment payload, stats : LoaderStats }\n  FRAG_LOADED = 'hlsFragLoaded',\n  // fired when a fragment has finished decrypting - data: { id : demuxer id, frag: fragment object, payload : fragment payload, stats : { tstart, tdecrypt } }\n  FRAG_DECRYPTED = 'hlsFragDecrypted',\n  // fired when Init Segment has been extracted from fragment - data: { id : demuxer id, frag: fragment object, moov : moov MP4 box, codecs : codecs found while parsing fragment }\n  FRAG_PARSING_INIT_SEGMENT = 'hlsFragParsingInitSegment',\n  // fired when parsing sei text is completed - data: { id : demuxer id, frag: fragment object, samples : [ sei samples pes ] }\n  FRAG_PARSING_USERDATA = 'hlsFragParsingUserdata',\n  // fired when parsing id3 is completed - data: { id : demuxer id, frag: fragment object, samples : [ id3 samples pes ] }\n  FRAG_PARSING_METADATA = 'hlsFragParsingMetadata',\n  // fired when data have been extracted from fragment - data: { id : demuxer id, frag: fragment object, data1 : moof MP4 box or TS fragments, data2 : mdat MP4 box or null}\n  // FRAG_PARSING_DATA = 'hlsFragParsingData',\n  // fired when fragment parsing is completed - data: { id : demuxer id, frag: fragment object }\n  FRAG_PARSED = 'hlsFragParsed',\n  // fired when fragment remuxed MP4 boxes have all been appended into SourceBuffer - data: { id : demuxer id, frag : fragment object, stats : LoaderStats }\n  FRAG_BUFFERED = 'hlsFragBuffered',\n  // fired when fragment matching with current media position is changing - data : { id : demuxer id, frag : fragment object }\n  FRAG_CHANGED = 'hlsFragChanged',\n  // Identifier for a FPS drop event - data: { currentDropped, currentDecoded, totalDroppedFrames }\n  FPS_DROP = 'hlsFpsDrop',\n  // triggered when FPS drop triggers auto level capping - data: { level, droppedLevel }\n  FPS_DROP_LEVEL_CAPPING = 'hlsFpsDropLevelCapping',\n  // triggered when maxAutoLevel changes - data { autoLevelCapping, levels, maxAutoLevel, minAutoLevel, maxHdcpLevel }\n  MAX_AUTO_LEVEL_UPDATED = 'hlsMaxAutoLevelUpdated',\n  // Identifier for an error event - data: { type : error type, details : error details, fatal : if true, hls.js cannot/will not try to recover, if false, hls.js will try to recover,other error specific data }\n  ERROR = 'hlsError',\n  // fired when hls.js instance starts destroying. Different from MEDIA_DETACHED as one could want to detach and reattach a media to the instance of hls.js to handle mid-rolls for example - data: { }\n  DESTROYING = 'hlsDestroying',\n  // fired when a decrypt key loading starts - data: { frag : fragment object }\n  KEY_LOADING = 'hlsKeyLoading',\n  // fired when a decrypt key loading is completed - data: { frag : fragment object, keyInfo : KeyLoaderInfo }\n  KEY_LOADED = 'hlsKeyLoaded',\n  // deprecated; please use BACK_BUFFER_REACHED - data : { bufferEnd: number }\n  LIVE_BACK_BUFFER_REACHED = 'hlsLiveBackBufferReached',\n  // fired when the back buffer is reached as defined by the backBufferLength config option - data : { bufferEnd: number }\n  BACK_BUFFER_REACHED = 'hlsBackBufferReached',\n  // fired after steering manifest has been loaded - data: { steeringManifest: SteeringManifest object, url: steering manifest URL }\n  STEERING_MANIFEST_LOADED = 'hlsSteeringManifestLoaded',\n}\n\n/**\n * Defines each Event type and payload by Event name. Used in {@link hls.js#HlsEventEmitter} to strongly type the event listener API.\n */\nexport interface HlsListeners {\n  [Events.MEDIA_ATTACHING]: (\n    event: Events.MEDIA_ATTACHING,\n    data: MediaAttachingData,\n  ) => void;\n  [Events.MEDIA_ATTACHED]: (\n    event: Events.MEDIA_ATTACHED,\n    data: MediaAttachedData,\n  ) => void;\n  [Events.MEDIA_DETACHING]: (event: Events.MEDIA_DETACHING) => void;\n  [Events.MEDIA_DETACHED]: (event: Events.MEDIA_DETACHED) => void;\n  [Events.BUFFER_RESET]: (event: Events.BUFFER_RESET) => void;\n  [Events.BUFFER_CODECS]: (\n    event: Events.BUFFER_CODECS,\n    data: BufferCodecsData,\n  ) => void;\n  [Events.BUFFER_CREATED]: (\n    event: Events.BUFFER_CREATED,\n    data: BufferCreatedData,\n  ) => void;\n  [Events.BUFFER_APPENDING]: (\n    event: Events.BUFFER_APPENDING,\n    data: BufferAppendingData,\n  ) => void;\n  [Events.BUFFER_APPENDED]: (\n    event: Events.BUFFER_APPENDED,\n    data: BufferAppendedData,\n  ) => void;\n  [Events.BUFFER_EOS]: (event: Events.BUFFER_EOS, data: BufferEOSData) => void;\n  [Events.BUFFER_FLUSHING]: (\n    event: Events.BUFFER_FLUSHING,\n    data: BufferFlushingData,\n  ) => void;\n  [Events.BUFFER_FLUSHED]: (\n    event: Events.BUFFER_FLUSHED,\n    data: BufferFlushedData,\n  ) => void;\n  [Events.MANIFEST_LOADING]: (\n    event: Events.MANIFEST_LOADING,\n    data: ManifestLoadingData,\n  ) => void;\n  [Events.MANIFEST_LOADED]: (\n    event: Events.MANIFEST_LOADED,\n    data: ManifestLoadedData,\n  ) => void;\n  [Events.MANIFEST_PARSED]: (\n    event: Events.MANIFEST_PARSED,\n    data: ManifestParsedData,\n  ) => void;\n  [Events.LEVEL_SWITCHING]: (\n    event: Events.LEVEL_SWITCHING,\n    data: LevelSwitchingData,\n  ) => void;\n  [Events.LEVEL_SWITCHED]: (\n    event: Events.LEVEL_SWITCHED,\n    data: LevelSwitchedData,\n  ) => void;\n  [Events.LEVEL_LOADING]: (\n    event: Events.LEVEL_LOADING,\n    data: LevelLoadingData,\n  ) => void;\n  [Events.LEVEL_LOADED]: (\n    event: Events.LEVEL_LOADED,\n    data: LevelLoadedData,\n  ) => void;\n  [Events.LEVEL_UPDATED]: (\n    event: Events.LEVEL_UPDATED,\n    data: LevelUpdatedData,\n  ) => void;\n  [Events.LEVEL_PTS_UPDATED]: (\n    event: Events.LEVEL_PTS_UPDATED,\n    data: LevelPTSUpdatedData,\n  ) => void;\n  [Events.LEVELS_UPDATED]: (\n    event: Events.LEVELS_UPDATED,\n    data: LevelsUpdatedData,\n  ) => void;\n  [Events.AUDIO_TRACKS_UPDATED]: (\n    event: Events.AUDIO_TRACKS_UPDATED,\n    data: AudioTracksUpdatedData,\n  ) => void;\n  [Events.AUDIO_TRACK_SWITCHING]: (\n    event: Events.AUDIO_TRACK_SWITCHING,\n    data: AudioTrackSwitchingData,\n  ) => void;\n  [Events.AUDIO_TRACK_SWITCHED]: (\n    event: Events.AUDIO_TRACK_SWITCHED,\n    data: AudioTrackSwitchedData,\n  ) => void;\n  [Events.AUDIO_TRACK_LOADING]: (\n    event: Events.AUDIO_TRACK_LOADING,\n    data: TrackLoadingData,\n  ) => void;\n  [Events.AUDIO_TRACK_LOADED]: (\n    event: Events.AUDIO_TRACK_LOADED,\n    data: AudioTrackLoadedData,\n  ) => void;\n  [Events.SUBTITLE_TRACKS_UPDATED]: (\n    event: Events.SUBTITLE_TRACKS_UPDATED,\n    data: SubtitleTracksUpdatedData,\n  ) => void;\n  [Events.SUBTITLE_TRACKS_CLEARED]: (\n    event: Events.SUBTITLE_TRACKS_CLEARED,\n  ) => void;\n  [Events.SUBTITLE_TRACK_SWITCH]: (\n    event: Events.SUBTITLE_TRACK_SWITCH,\n    data: SubtitleTrackSwitchData,\n  ) => void;\n  [Events.SUBTITLE_TRACK_LOADING]: (\n    event: Events.SUBTITLE_TRACK_LOADING,\n    data: TrackLoadingData,\n  ) => void;\n  [Events.SUBTITLE_TRACK_LOADED]: (\n    event: Events.SUBTITLE_TRACK_LOADED,\n    data: SubtitleTrackLoadedData,\n  ) => void;\n  [Events.SUBTITLE_FRAG_PROCESSED]: (\n    event: Events.SUBTITLE_FRAG_PROCESSED,\n    data: SubtitleFragProcessedData,\n  ) => void;\n  [Events.CUES_PARSED]: (\n    event: Events.CUES_PARSED,\n    data: CuesParsedData,\n  ) => void;\n  [Events.NON_NATIVE_TEXT_TRACKS_FOUND]: (\n    event: Events.NON_NATIVE_TEXT_TRACKS_FOUND,\n    data: NonNativeTextTracksData,\n  ) => void;\n  [Events.INIT_PTS_FOUND]: (\n    event: Events.INIT_PTS_FOUND,\n    data: InitPTSFoundData,\n  ) => void;\n  [Events.FRAG_LOADING]: (\n    event: Events.FRAG_LOADING,\n    data: FragLoadingData,\n  ) => void;\n  // [Events.FRAG_LOAD_PROGRESS]: TodoEventType\n  [Events.FRAG_LOAD_EMERGENCY_ABORTED]: (\n    event: Events.FRAG_LOAD_EMERGENCY_ABORTED,\n    data: FragLoadEmergencyAbortedData,\n  ) => void;\n  [Events.FRAG_LOADED]: (\n    event: Events.FRAG_LOADED,\n    data: FragLoadedData,\n  ) => void;\n  [Events.FRAG_DECRYPTED]: (\n    event: Events.FRAG_DECRYPTED,\n    data: FragDecryptedData,\n  ) => void;\n  [Events.FRAG_PARSING_INIT_SEGMENT]: (\n    event: Events.FRAG_PARSING_INIT_SEGMENT,\n    data: FragParsingInitSegmentData,\n  ) => void;\n  [Events.FRAG_PARSING_USERDATA]: (\n    event: Events.FRAG_PARSING_USERDATA,\n    data: FragParsingUserdataData,\n  ) => void;\n  [Events.FRAG_PARSING_METADATA]: (\n    event: Events.FRAG_PARSING_METADATA,\n    data: FragParsingMetadataData,\n  ) => void;\n  // [Events.FRAG_PARSING_DATA]: TodoEventType\n  [Events.FRAG_PARSED]: (\n    event: Events.FRAG_PARSED,\n    data: FragParsedData,\n  ) => void;\n  [Events.FRAG_BUFFERED]: (\n    event: Events.FRAG_BUFFERED,\n    data: FragBufferedData,\n  ) => void;\n  [Events.FRAG_CHANGED]: (\n    event: Events.FRAG_CHANGED,\n    data: FragChangedData,\n  ) => void;\n  [Events.FPS_DROP]: (event: Events.FPS_DROP, data: FPSDropData) => void;\n  [Events.FPS_DROP_LEVEL_CAPPING]: (\n    event: Events.FPS_DROP_LEVEL_CAPPING,\n    data: FPSDropLevelCappingData,\n  ) => void;\n  [Events.MAX_AUTO_LEVEL_UPDATED]: (\n    event: Events.MAX_AUTO_LEVEL_UPDATED,\n    data: MaxAutoLevelUpdatedData,\n  ) => void;\n  [Events.ERROR]: (event: Events.ERROR, data: ErrorData) => void;\n  [Events.DESTROYING]: (event: Events.DESTROYING) => void;\n  [Events.KEY_LOADING]: (\n    event: Events.KEY_LOADING,\n    data: KeyLoadingData,\n  ) => void;\n  [Events.KEY_LOADED]: (event: Events.KEY_LOADED, data: KeyLoadedData) => void;\n  [Events.LIVE_BACK_BUFFER_REACHED]: (\n    event: Events.LIVE_BACK_BUFFER_REACHED,\n    data: LiveBackBufferData,\n  ) => void;\n  [Events.BACK_BUFFER_REACHED]: (\n    event: Events.BACK_BUFFER_REACHED,\n    data: BackBufferData,\n  ) => void;\n  [Events.STEERING_MANIFEST_LOADED]: (\n    event: Events.STEERING_MANIFEST_LOADED,\n    data: SteeringManifestLoadedData,\n  ) => void;\n}\nexport interface HlsEventEmitter {\n  on<E extends keyof HlsListeners, Context = undefined>(\n    event: E,\n    listener: HlsListeners[E],\n    context?: Context,\n  ): void;\n  once<E extends keyof HlsListeners, Context = undefined>(\n    event: E,\n    listener: HlsListeners[E],\n    context?: Context,\n  ): void;\n\n  removeAllListeners<E extends keyof HlsListeners>(event?: E): void;\n  off<E extends keyof HlsListeners, Context = undefined>(\n    event: E,\n    listener?: HlsListeners[E],\n    context?: Context,\n    once?: boolean,\n  ): void;\n\n  listeners<E extends keyof HlsListeners>(event: E): HlsListeners[E][];\n  emit<E extends keyof HlsListeners>(\n    event: E,\n    name: E,\n    eventObject: Parameters<HlsListeners[E]>[1],\n  ): boolean;\n  listenerCount<E extends keyof HlsListeners>(event: E): number;\n}\n", "export enum ErrorTypes {\n  // Identifier for a network error (loading error / timeout ...)\n  NETWORK_ERROR = 'networkError',\n  // Identifier for a media Error (video/parsing/mediasource error)\n  MEDIA_ERROR = 'mediaError',\n  // EME (encrypted media extensions) errors\n  KEY_SYSTEM_ERROR = 'keySystemError',\n  // Identifier for a mux Error (demuxing/remuxing)\n  MUX_ERROR = 'muxError',\n  // Identifier for all other errors\n  OTHER_ERROR = 'otherError',\n}\n\nexport enum ErrorDetails {\n  KEY_SYSTEM_NO_KEYS = 'keySystemNoKeys',\n  KEY_SYSTEM_NO_ACCESS = 'keySystemNoAccess',\n  KEY_SYSTEM_NO_SESSION = 'keySystemNoSession',\n  KEY_SYSTEM_NO_CONFIGURED_LICENSE = 'keySystemNoConfiguredLicense',\n  KEY_SYSTEM_LICENSE_REQUEST_FAILED = 'keySystemLicenseRequestFailed',\n  KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED = 'keySystemServerCertificateRequestFailed',\n  KEY_SYSTEM_SERVER_CERTIFICATE_UPDATE_FAILED = 'keySystemServerCertificateUpdateFailed',\n  KEY_SYSTEM_SESSION_UPDATE_FAILED = 'keySystemSessionUpdateFailed',\n  KEY_SYSTEM_STATUS_OUTPUT_RESTRICTED = 'keySystemStatusOutputRestricted',\n  KEY_SYSTEM_STATUS_INTERNAL_ERROR = 'keySystemStatusInternalError',\n  // Identifier for a manifest load error - data: { url : faulty URL, response : { code: error code, text: error text }}\n  MANIFEST_LOAD_ERROR = 'manifestLoadError',\n  // Identifier for a manifest load timeout - data: { url : faulty URL, response : { code: error code, text: error text }}\n  MANIFEST_LOAD_TIMEOUT = 'manifestLoadTimeOut',\n  // Identifier for a manifest parsing error - data: { url : faulty URL, reason : error reason}\n  MANIFEST_PARSING_ERROR = 'manifestParsingError',\n  // Identifier for a manifest with only incompatible codecs error - data: { url : faulty URL, reason : error reason}\n  MANIFEST_INCOMPATIBLE_CODECS_ERROR = 'manifestIncompatibleCodecsError',\n  // Identifier for a level which contains no fragments - data: { url: faulty URL, reason: \"no fragments found in level\", level: index of the bad level }\n  LEVEL_EMPTY_ERROR = 'levelEmptyError',\n  // Identifier for a level load error - data: { url : faulty URL, response : { code: error code, text: error text }}\n  LEVEL_LOAD_ERROR = 'levelLoadError',\n  // Identifier for a level load timeout - data: { url : faulty URL, response : { code: error code, text: error text }}\n  LEVEL_LOAD_TIMEOUT = 'levelLoadTimeOut',\n  // Identifier for a level parse error - data: { url : faulty URL, error: Error, reason: error message }\n  LEVEL_PARSING_ERROR = 'levelParsingError',\n  // Identifier for a level switch error - data: { level : faulty level Id, event : error description}\n  LEVEL_SWITCH_ERROR = 'levelSwitchError',\n  // Identifier for an audio track load error - data: { url : faulty URL, response : { code: error code, text: error text }}\n  AUDIO_TRACK_LOAD_ERROR = 'audioTrackLoadError',\n  // Identifier for an audio track load timeout - data: { url : faulty URL, response : { code: error code, text: error text }}\n  AUDIO_TRACK_LOAD_TIMEOUT = 'audioTrackLoadTimeOut',\n  // Identifier for a subtitle track load error - data: { url : faulty URL, response : { code: error code, text: error text }}\n  SUBTITLE_LOAD_ERROR = 'subtitleTrackLoadError',\n  // Identifier for a subtitle track load timeout - data: { url : faulty URL, response : { code: error code, text: error text }}\n  SUBTITLE_TRACK_LOAD_TIMEOUT = 'subtitleTrackLoadTimeOut',\n  // Identifier for fragment load error - data: { frag : fragment object, response : { code: error code, text: error text }}\n  FRAG_LOAD_ERROR = 'fragLoadError',\n  // Identifier for fragment load timeout error - data: { frag : fragment object}\n  FRAG_LOAD_TIMEOUT = 'fragLoadTimeOut',\n  // Identifier for a fragment decryption error event - data: {id : demuxer Id,frag: fragment object, reason : parsing error description }\n  FRAG_DECRYPT_ERROR = 'fragDecryptError',\n  // Identifier for a fragment parsing error event - data: { id : demuxer Id, reason : parsing error description }\n  // will be renamed DEMUX_PARSING_ERROR and switched to MUX_ERROR in the next major release\n  FRAG_PARSING_ERROR = 'fragParsingError',\n  // Identifier for a fragment or part load skipped because of a GAP tag or attribute\n  FRAG_GAP = 'fragGap',\n  // Identifier for a remux alloc error event - data: { id : demuxer Id, frag : fragment object, bytes : nb of bytes on which allocation failed , reason : error text }\n  REMUX_ALLOC_ERROR = 'remuxAllocError',\n  // Identifier for decrypt key load error - data: { frag : fragment object, response : { code: error code, text: error text }}\n  KEY_LOAD_ERROR = 'keyLoadError',\n  // Identifier for decrypt key load timeout error - data: { frag : fragment object}\n  KEY_LOAD_TIMEOUT = 'keyLoadTimeOut',\n  // Triggered when an exception occurs while adding a sourceBuffer to MediaSource - data : { error : exception , mimeType : mimeType }\n  BUFFER_ADD_CODEC_ERROR = 'bufferAddCodecError',\n  // Triggered when source buffer(s) could not be created using level (manifest CODECS attribute), parsed media, or best guess codec(s) - data: { reason : error reason }\n  BUFFER_INCOMPATIBLE_CODECS_ERROR = 'bufferIncompatibleCodecsError',\n  // Identifier for a buffer append error - data: append error description\n  BUFFER_APPEND_ERROR = 'bufferAppendError',\n  // Identifier for a buffer appending error event - data: appending error description\n  BUFFER_APPENDING_ERROR = 'bufferAppendingError',\n  // Identifier for a buffer stalled error event\n  BUFFER_STALLED_ERROR = 'bufferStalledError',\n  // Identifier for a buffer full event\n  BUFFER_FULL_ERROR = 'bufferFullError',\n  // Identifier for a buffer seek over hole event\n  BUFFER_SEEK_OVER_HOLE = 'bufferSeekOverHole',\n  // Identifier for a buffer nudge on stall (playback is stuck although currentTime is in a buffered area)\n  BUFFER_NUDGE_ON_STALL = 'bufferNudgeOnStall',\n  // Identifier for an internal exception happening inside hls.js while handling an event\n  INTERNAL_EXCEPTION = 'internalException',\n  // Identifier for an internal call to abort a loader\n  INTERNAL_ABORTED = 'aborted',\n  // Uncategorized error\n  UNKNOWN = 'unknown',\n}\n", "export interface ILogFunction {\n  (message?: any, ...optionalParams: any[]): void;\n}\n\nexport interface ILogger {\n  trace: ILogFunction;\n  debug: ILogFunction;\n  log: ILogFunction;\n  warn: ILogFunction;\n  info: ILogFunction;\n  error: ILogFunction;\n}\n\nconst noop: ILogFunction = function () {};\n\nconst fakeLogger: ILogger = {\n  trace: noop,\n  debug: noop,\n  log: noop,\n  warn: noop,\n  info: noop,\n  error: noop,\n};\n\nlet exportedLogger: ILogger = fakeLogger;\n\n// let lastCallTime;\n// function formatMsgWithTimeInfo(type, msg) {\n//   const now = Date.now();\n//   const diff = lastCallTime ? '+' + (now - lastCallTime) : '0';\n//   lastCallTime = now;\n//   msg = (new Date(now)).toISOString() + ' | [' +  type + '] > ' + msg + ' ( ' + diff + ' ms )';\n//   return msg;\n// }\n\nfunction consolePrintFn(type: string): ILogFunction {\n  const func: ILogFunction = self.console[type];\n  if (func) {\n    return func.bind(self.console, `[${type}] >`);\n  }\n  return noop;\n}\n\nfunction exportLoggerFunctions(\n  debugConfig: boolean | ILogger,\n  ...functions: string[]\n): void {\n  functions.forEach(function (type) {\n    exportedLogger[type] = debugConfig[type]\n      ? debugConfig[type].bind(debugConfig)\n      : consolePrintFn(type);\n  });\n}\n\nexport function enableLogs(debugConfig: boolean | ILogger, id: string): void {\n  // check that console is available\n  if (\n    (typeof console === 'object' && debugConfig === true) ||\n    typeof debugConfig === 'object'\n  ) {\n    exportLoggerFunctions(\n      debugConfig,\n      // Remove out from list here to hard-disable a log-level\n      // 'trace',\n      'debug',\n      'log',\n      'info',\n      'warn',\n      'error',\n    );\n    // Some browsers don't allow to use bind on console object anyway\n    // fallback to default if needed\n    try {\n      exportedLogger.log(\n        `Debug logs enabled for \"${id}\" in hls.js version ${__VERSION__}`,\n      );\n    } catch (e) {\n      exportedLogger = fakeLogger;\n    }\n  } else {\n    exportedLogger = fakeLogger;\n  }\n}\n\nexport const logger: ILogger = exportedLogger;\n", "const DECIMAL_RESOLUTION_REGEX = /^(\\d+)x(\\d+)$/;\nconst ATTR_LIST_REGEX = /(.+?)=(\".*?\"|.*?)(?:,|$)/g;\n\n// adapted from https://github.com/kanongil/node-m3u8parse/blob/master/attrlist.js\nexport class AttrList {\n  [key: string]: any;\n\n  constructor(attrs: string | Record<string, any>) {\n    if (typeof attrs === 'string') {\n      attrs = AttrList.parseAttrList(attrs);\n    }\n    Object.assign(this, attrs);\n  }\n\n  get clientAttrs(): string[] {\n    return Object.keys(this).filter((attr) => attr.substring(0, 2) === 'X-');\n  }\n\n  decimalInteger(attrName: string): number {\n    const intValue = parseInt(this[attrName], 10);\n    if (intValue > Number.MAX_SAFE_INTEGER) {\n      return Infinity;\n    }\n\n    return intValue;\n  }\n\n  hexadecimalInteger(attrName: string) {\n    if (this[attrName]) {\n      let stringValue = (this[attrName] || '0x').slice(2);\n      stringValue = (stringValue.length & 1 ? '0' : '') + stringValue;\n\n      const value = new Uint8Array(stringValue.length / 2);\n      for (let i = 0; i < stringValue.length / 2; i++) {\n        value[i] = parseInt(stringValue.slice(i * 2, i * 2 + 2), 16);\n      }\n\n      return value;\n    } else {\n      return null;\n    }\n  }\n\n  hexadecimalIntegerAsNumber(attrName: string): number {\n    const intValue = parseInt(this[attrName], 16);\n    if (intValue > Number.MAX_SAFE_INTEGER) {\n      return Infinity;\n    }\n\n    return intValue;\n  }\n\n  decimalFloatingPoint(attrName: string): number {\n    return parseFloat(this[attrName]);\n  }\n\n  optionalFloat(attrName: string, defaultValue: number): number {\n    const value = this[attrName];\n    return value ? parseFloat(value) : defaultValue;\n  }\n\n  enumeratedString(attrName: string): string | undefined {\n    return this[attrName];\n  }\n\n  bool(attrName: string): boolean {\n    return this[attrName] === 'YES';\n  }\n\n  decimalResolution(attrName: string):\n    | {\n        width: number;\n        height: number;\n      }\n    | undefined {\n    const res = DECIMAL_RESOLUTION_REGEX.exec(this[attrName]);\n    if (res === null) {\n      return undefined;\n    }\n\n    return {\n      width: parseInt(res[1], 10),\n      height: parseInt(res[2], 10),\n    };\n  }\n\n  static parseAttrList(input: string): Record<string, any> {\n    let match;\n    const attrs = {};\n    const quote = '\"';\n    ATTR_LIST_REGEX.lastIndex = 0;\n    while ((match = ATTR_LIST_REGEX.exec(input)) !== null) {\n      let value = match[2];\n\n      if (\n        value.indexOf(quote) === 0 &&\n        value.lastIndexOf(quote) === value.length - 1\n      ) {\n        value = value.slice(1, -1);\n      }\n      const name = match[1].trim();\n      attrs[name] = value;\n    }\n    return attrs;\n  }\n}\n", "import { AttrList } from '../utils/attr-list';\nimport { logger } from '../utils/logger';\n\n// Avoid exporting const enum so that these values can be inlined\nconst enum DateRangeAttribute {\n  ID = 'ID',\n  CLASS = 'CLASS',\n  START_DATE = 'START-DATE',\n  DURATION = 'DURATION',\n  END_DATE = 'END-DATE',\n  END_ON_NEXT = 'END-ON-NEXT',\n  PLANNED_DURATION = 'PLANNED-DURATION',\n  SCTE35_OUT = 'SCTE35-OUT',\n  SCTE35_IN = 'SCTE35-IN',\n}\n\nexport function isDateRangeCueAttribute(attrName: string): boolean {\n  return (\n    attrName !== DateRangeAttribute.ID &&\n    attrName !== DateRangeAttribute.CLASS &&\n    attrName !== DateRangeAttribute.START_DATE &&\n    attrName !== DateRangeAttribute.DURATION &&\n    attrName !== DateRangeAttribute.END_DATE &&\n    attrName !== DateRangeAttribute.END_ON_NEXT\n  );\n}\n\nexport function isSCTE35Attribute(attrName: string): boolean {\n  return (\n    attrName === DateRangeAttribute.SCTE35_OUT ||\n    attrName === DateRangeAttribute.SCTE35_IN\n  );\n}\n\nexport class DateRange {\n  public attr: AttrList;\n  private _startDate: Date;\n  private _endDate?: Date;\n  private _badValueForSameId?: string;\n\n  constructor(dateRangeAttr: AttrList, dateRangeWithSameId?: DateRange) {\n    if (dateRangeWithSameId) {\n      const previousAttr = dateRangeWithSameId.attr;\n      for (const key in previousAttr) {\n        if (\n          Object.prototype.hasOwnProperty.call(dateRangeAttr, key) &&\n          dateRangeAttr[key] !== previousAttr[key]\n        ) {\n          logger.warn(\n            `DATERANGE tag attribute: \"${key}\" does not match for tags with ID: \"${dateRangeAttr.ID}\"`,\n          );\n          this._badValueForSameId = key;\n          break;\n        }\n      }\n      // Merge DateRange tags with the same ID\n      dateRangeAttr = Object.assign(\n        new AttrList({}),\n        previousAttr,\n        dateRangeAttr,\n      );\n    }\n    this.attr = dateRangeAttr;\n    this._startDate = new Date(dateRangeAttr[DateRangeAttribute.START_DATE]);\n    if (DateRangeAttribute.END_DATE in this.attr) {\n      const endDate = new Date(this.attr[DateRangeAttribute.END_DATE]);\n      if (Number.isFinite(endDate.getTime())) {\n        this._endDate = endDate;\n      }\n    }\n  }\n\n  get id(): string {\n    return this.attr.ID;\n  }\n\n  get class(): string {\n    return this.attr.CLASS;\n  }\n\n  get startDate(): Date {\n    return this._startDate;\n  }\n\n  get endDate(): Date | null {\n    if (this._endDate) {\n      return this._endDate;\n    }\n    const duration = this.duration;\n    if (duration !== null) {\n      return new Date(this._startDate.getTime() + duration * 1000);\n    }\n    return null;\n  }\n\n  get duration(): number | null {\n    if (DateRangeAttribute.DURATION in this.attr) {\n      const duration = this.attr.decimalFloatingPoint(\n        DateRangeAttribute.DURATION,\n      );\n      if (Number.isFinite(duration)) {\n        return duration;\n      }\n    } else if (this._endDate) {\n      return (this._endDate.getTime() - this._startDate.getTime()) / 1000;\n    }\n    return null;\n  }\n\n  get plannedDuration(): number | null {\n    if (DateRangeAttribute.PLANNED_DURATION in this.attr) {\n      return this.attr.decimalFloatingPoint(\n        DateRangeAttribute.PLANNED_DURATION,\n      );\n    }\n    return null;\n  }\n\n  get endOnNext(): boolean {\n    return this.attr.bool(DateRangeAttribute.END_ON_NEXT);\n  }\n\n  get isValid(): boolean {\n    return (\n      !!this.id &&\n      !this._badValueForSameId &&\n      Number.isFinite(this.startDate.getTime()) &&\n      (this.duration === null || this.duration >= 0) &&\n      (!this.endOnNext || !!this.class)\n    );\n  }\n}\n", "import type {\n  HlsPerformanceTiming,\n  HlsProgressivePerformanceTiming,\n  LoaderStats,\n} from '../types/loader';\n\nexport class LoadStats implements LoaderStats {\n  aborted: boolean = false;\n  loaded: number = 0;\n  retry: number = 0;\n  total: number = 0;\n  chunkCount: number = 0;\n  bwEstimate: number = 0;\n  loading: HlsProgressivePerformanceTiming = { start: 0, first: 0, end: 0 };\n  parsing: HlsPerformanceTiming = { start: 0, end: 0 };\n  buffering: HlsProgressivePerformanceTiming = { start: 0, first: 0, end: 0 };\n}\n", "import { buildAbsoluteURL } from 'url-toolkit';\nimport { LevelKey } from './level-key';\nimport { LoadStats } from './load-stats';\nimport { AttrList } from '../utils/attr-list';\nimport type {\n  FragmentLoaderContext,\n  KeyLoaderContext,\n  Loader,\n  PlaylistLevelType,\n} from '../types/loader';\nimport type { KeySystemFormats } from '../utils/mediakeys-helper';\n\nexport const enum ElementaryStreamTypes {\n  AUDIO = 'audio',\n  VIDEO = 'video',\n  AUDIOVIDEO = 'audiovideo',\n}\n\nexport interface ElementaryStreamInfo {\n  startPTS: number;\n  endPTS: number;\n  startDTS: number;\n  endDTS: number;\n  partial?: boolean;\n}\n\nexport type ElementaryStreams = Record<\n  ElementaryStreamTypes,\n  ElementaryStreamInfo | null\n>;\n\nexport class BaseSegment {\n  private _byteRange: [number, number] | null = null;\n  private _url: string | null = null;\n\n  // baseurl is the URL to the playlist\n  public readonly baseurl: string;\n  // relurl is the portion of the URL that comes from inside the playlist.\n  public relurl?: string;\n  // Holds the types of data this fragment supports\n  public elementaryStreams: ElementaryStreams = {\n    [ElementaryStreamTypes.AUDIO]: null,\n    [ElementaryStreamTypes.VIDEO]: null,\n    [ElementaryStreamTypes.AUDIOVIDEO]: null,\n  };\n\n  constructor(baseurl: string) {\n    this.baseurl = baseurl;\n  }\n\n  // setByteRange converts a EXT-X-BYTERANGE attribute into a two element array\n  setByteRange(value: string, previous?: BaseSegment) {\n    const params = value.split('@', 2);\n    let start: number;\n    if (params.length === 1) {\n      start = previous?.byteRangeEndOffset || 0;\n    } else {\n      start = parseInt(params[1]);\n    }\n    this._byteRange = [start, parseInt(params[0]) + start];\n  }\n\n  get byteRange(): [number, number] | [] {\n    if (!this._byteRange) {\n      return [];\n    }\n\n    return this._byteRange;\n  }\n\n  get byteRangeStartOffset(): number | undefined {\n    return this.byteRange[0];\n  }\n\n  get byteRangeEndOffset(): number | undefined {\n    return this.byteRange[1];\n  }\n\n  get url(): string {\n    if (!this._url && this.baseurl && this.relurl) {\n      this._url = buildAbsoluteURL(this.baseurl, this.relurl, {\n        alwaysNormalize: true,\n      });\n    }\n    return this._url || '';\n  }\n\n  set url(value: string) {\n    this._url = value;\n  }\n}\n\n/**\n * Object representing parsed data from an HLS Segment. Found in {@link hls.js#LevelDetails.fragments}.\n */\nexport class Fragment extends BaseSegment {\n  private _decryptdata: LevelKey | null = null;\n\n  public rawProgramDateTime: string | null = null;\n  public programDateTime: number | null = null;\n  public tagList: Array<string[]> = [];\n\n  // EXTINF has to be present for a m3u8 to be considered valid\n  public duration: number = 0;\n  // sn notates the sequence number for a segment, and if set to a string can be 'initSegment'\n  public sn: number | 'initSegment' = 0;\n  // levelkeys are the EXT-X-KEY tags that apply to this segment for decryption\n  // core difference from the private field _decryptdata is the lack of the initialized IV\n  // _decryptdata will set the IV for this segment based on the segment number in the fragment\n  public levelkeys?: { [key: string]: LevelKey };\n  // A string representing the fragment type\n  public readonly type: PlaylistLevelType;\n  // A reference to the loader. Set while the fragment is loading, and removed afterwards. Used to abort fragment loading\n  public loader: Loader<FragmentLoaderContext> | null = null;\n  // A reference to the key loader. Set while the key is loading, and removed afterwards. Used to abort key loading\n  public keyLoader: Loader<KeyLoaderContext> | null = null;\n  // The level/track index to which the fragment belongs\n  public level: number = -1;\n  // The continuity counter of the fragment\n  public cc: number = 0;\n  // The starting Presentation Time Stamp (PTS) of the fragment. Set after transmux complete.\n  public startPTS?: number;\n  // The ending Presentation Time Stamp (PTS) of the fragment. Set after transmux complete.\n  public endPTS?: number;\n  // The starting Decode Time Stamp (DTS) of the fragment. Set after transmux complete.\n  public startDTS!: number;\n  // The ending Decode Time Stamp (DTS) of the fragment. Set after transmux complete.\n  public endDTS!: number;\n  // The start time of the fragment, as listed in the manifest. Updated after transmux complete.\n  public start: number = 0;\n  // Set by `updateFragPTSDTS` in level-helper\n  public deltaPTS?: number;\n  // The maximum starting Presentation Time Stamp (audio/video PTS) of the fragment. Set after transmux complete.\n  public maxStartPTS?: number;\n  // The minimum ending Presentation Time Stamp (audio/video PTS) of the fragment. Set after transmux complete.\n  public minEndPTS?: number;\n  // Load/parse timing information\n  public stats: LoadStats = new LoadStats();\n  // Init Segment bytes (unset for media segments)\n  public data?: Uint8Array;\n  // A flag indicating whether the segment was downloaded in order to test bitrate, and was not buffered\n  public bitrateTest: boolean = false;\n  // #EXTINF  segment title\n  public title: string | null = null;\n  // The Media Initialization Section for this segment\n  public initSegment: Fragment | null = null;\n  // Fragment is the last fragment in the media playlist\n  public endList?: boolean;\n  // Fragment is marked by an EXT-X-GAP tag indicating that it does not contain media data and should not be loaded\n  public gap?: boolean;\n  // Deprecated\n  public urlId: number = 0;\n\n  constructor(type: PlaylistLevelType, baseurl: string) {\n    super(baseurl);\n    this.type = type;\n  }\n\n  get decryptdata(): LevelKey | null {\n    const { levelkeys } = this;\n    if (!levelkeys && !this._decryptdata) {\n      return null;\n    }\n\n    if (!this._decryptdata && this.levelkeys && !this.levelkeys.NONE) {\n      const key = this.levelkeys.identity;\n      if (key) {\n        this._decryptdata = key.getDecryptData(this.sn);\n      } else {\n        const keyFormats = Object.keys(this.levelkeys);\n        if (keyFormats.length === 1) {\n          return (this._decryptdata = this.levelkeys[\n            keyFormats[0]\n          ].getDecryptData(this.sn));\n        } else {\n          // Multiple keys. key-loader to call Fragment.setKeyFormat based on selected key-system.\n        }\n      }\n    }\n\n    return this._decryptdata;\n  }\n\n  get end(): number {\n    return this.start + this.duration;\n  }\n\n  get endProgramDateTime() {\n    if (this.programDateTime === null) {\n      return null;\n    }\n\n    if (!Number.isFinite(this.programDateTime)) {\n      return null;\n    }\n\n    const duration = !Number.isFinite(this.duration) ? 0 : this.duration;\n\n    return this.programDateTime + duration * 1000;\n  }\n\n  get encrypted() {\n    // At the m3u8-parser level we need to add support for manifest signalled keyformats\n    // when we want the fragment to start reporting that it is encrypted.\n    // Currently, keyFormat will only be set for identity keys\n    if (this._decryptdata?.encrypted) {\n      return true;\n    } else if (this.levelkeys) {\n      const keyFormats = Object.keys(this.levelkeys);\n      const len = keyFormats.length;\n      if (len > 1 || (len === 1 && this.levelkeys[keyFormats[0]].encrypted)) {\n        return true;\n      }\n    }\n\n    return false;\n  }\n\n  setKeyFormat(keyFormat: KeySystemFormats) {\n    if (this.levelkeys) {\n      const key = this.levelkeys[keyFormat];\n      if (key && !this._decryptdata) {\n        this._decryptdata = key.getDecryptData(this.sn);\n      }\n    }\n  }\n\n  abortRequests(): void {\n    this.loader?.abort();\n    this.keyLoader?.abort();\n  }\n\n  setElementaryStreamInfo(\n    type: ElementaryStreamTypes,\n    startPTS: number,\n    endPTS: number,\n    startDTS: number,\n    endDTS: number,\n    partial: boolean = false,\n  ) {\n    const { elementaryStreams } = this;\n    const info = elementaryStreams[type];\n    if (!info) {\n      elementaryStreams[type] = {\n        startPTS,\n        endPTS,\n        startDTS,\n        endDTS,\n        partial,\n      };\n      return;\n    }\n\n    info.startPTS = Math.min(info.startPTS, startPTS);\n    info.endPTS = Math.max(info.endPTS, endPTS);\n    info.startDTS = Math.min(info.startDTS, startDTS);\n    info.endDTS = Math.max(info.endDTS, endDTS);\n  }\n\n  clearElementaryStreamInfo() {\n    const { elementaryStreams } = this;\n    elementaryStreams[ElementaryStreamTypes.AUDIO] = null;\n    elementaryStreams[ElementaryStreamTypes.VIDEO] = null;\n    elementaryStreams[ElementaryStreamTypes.AUDIOVIDEO] = null;\n  }\n}\n\n/**\n * Object representing parsed data from an HLS Partial Segment. Found in {@link hls.js#LevelDetails.partList}.\n */\nexport class Part extends BaseSegment {\n  public readonly fragOffset: number = 0;\n  public readonly duration: number = 0;\n  public readonly gap: boolean = false;\n  public readonly independent: boolean = false;\n  public readonly relurl: string;\n  public readonly fragment: Fragment;\n  public readonly index: number;\n  public stats: LoadStats = new LoadStats();\n\n  constructor(\n    partAttrs: AttrList,\n    frag: Fragment,\n    baseurl: string,\n    index: number,\n    previous?: Part,\n  ) {\n    super(baseurl);\n    this.duration = partAttrs.decimalFloatingPoint('DURATION');\n    this.gap = partAttrs.bool('GAP');\n    this.independent = partAttrs.bool('INDEPENDENT');\n    this.relurl = partAttrs.enumeratedString('URI') as string;\n    this.fragment = frag;\n    this.index = index;\n    const byteRange = partAttrs.enumeratedString('BYTERANGE');\n    if (byteRange) {\n      this.setByteRange(byteRange, previous);\n    }\n    if (previous) {\n      this.fragOffset = previous.fragOffset + previous.duration;\n    }\n  }\n\n  get start(): number {\n    return this.fragment.start + this.fragOffset;\n  }\n\n  get end(): number {\n    return this.start + this.duration;\n  }\n\n  get loaded(): boolean {\n    const { elementaryStreams } = this;\n    return !!(\n      elementaryStreams.audio ||\n      elementaryStreams.video ||\n      elementaryStreams.audiovideo\n    );\n  }\n}\n", "import { Part } from './fragment';\nimport type { Fragment } from './fragment';\nimport type { AttrList } from '../utils/attr-list';\nimport type { DateRange } from './date-range';\nimport type { VariableMap } from '../types/level';\n\nconst DEFAULT_TARGET_DURATION = 10;\n\n/**\n * Object representing parsed data from an HLS Media Playlist. Found in {@link hls.js#Level.details}.\n */\nexport class LevelDetails {\n  public PTSKnown: boolean = false;\n  public alignedSliding: boolean = false;\n  public averagetargetduration?: number;\n  public endCC: number = 0;\n  public endSN: number = 0;\n  public fragments: Fragment[];\n  public fragmentHint?: Fragment;\n  public partList: Part[] | null = null;\n  public dateRanges: Record<string, DateRange>;\n  public live: boolean = true;\n  public ageHeader: number = 0;\n  public advancedDateTime?: number;\n  public updated: boolean = true;\n  public advanced: boolean = true;\n  public availabilityDelay?: number; // Manifest reload synchronization\n  public misses: number = 0;\n  public startCC: number = 0;\n  public startSN: number = 0;\n  public startTimeOffset: number | null = null;\n  public targetduration: number = 0;\n  public totalduration: number = 0;\n  public type: string | null = null;\n  public url: string;\n  public m3u8: string = '';\n  public version: number | null = null;\n  public canBlockReload: boolean = false;\n  public canSkipUntil: number = 0;\n  public canSkipDateRanges: boolean = false;\n  public skippedSegments: number = 0;\n  public recentlyRemovedDateranges?: string[];\n  public partHoldBack: number = 0;\n  public holdBack: number = 0;\n  public partTarget: number = 0;\n  public preloadHint?: AttrList;\n  public renditionReports?: AttrList[];\n  public tuneInGoal: number = 0;\n  public deltaUpdateFailed?: boolean;\n  public driftStartTime: number = 0;\n  public driftEndTime: number = 0;\n  public driftStart: number = 0;\n  public driftEnd: number = 0;\n  public encryptedFragments: Fragment[];\n  public playlistParsingError: Error | null = null;\n  public variableList: VariableMap | null = null;\n  public hasVariableRefs = false;\n\n  constructor(baseUrl: string) {\n    this.fragments = [];\n    this.encryptedFragments = [];\n    this.dateRanges = {};\n    this.url = baseUrl;\n  }\n\n  reloaded(previous: LevelDetails | undefined) {\n    if (!previous) {\n      this.advanced = true;\n      this.updated = true;\n      return;\n    }\n    const partSnDiff = this.lastPartSn - previous.lastPartSn;\n    const partIndexDiff = this.lastPartIndex - previous.lastPartIndex;\n    this.updated =\n      this.endSN !== previous.endSN ||\n      !!partIndexDiff ||\n      !!partSnDiff ||\n      !this.live;\n    this.advanced =\n      this.endSN > previous.endSN ||\n      partSnDiff > 0 ||\n      (partSnDiff === 0 && partIndexDiff > 0);\n    if (this.updated || this.advanced) {\n      this.misses = Math.floor(previous.misses * 0.6);\n    } else {\n      this.misses = previous.misses + 1;\n    }\n    this.availabilityDelay = previous.availabilityDelay;\n  }\n\n  get hasProgramDateTime(): boolean {\n    if (this.fragments.length) {\n      return Number.isFinite(\n        this.fragments[this.fragments.length - 1].programDateTime as number,\n      );\n    }\n    return false;\n  }\n\n  get levelTargetDuration(): number {\n    return (\n      this.averagetargetduration ||\n      this.targetduration ||\n      DEFAULT_TARGET_DURATION\n    );\n  }\n\n  get drift(): number {\n    const runTime = this.driftEndTime - this.driftStartTime;\n    if (runTime > 0) {\n      const runDuration = this.driftEnd - this.driftStart;\n      return (runDuration * 1000) / runTime;\n    }\n    return 1;\n  }\n\n  get edge(): number {\n    return this.partEnd || this.fragmentEnd;\n  }\n\n  get partEnd(): number {\n    if (this.partList?.length) {\n      return this.partList[this.partList.length - 1].end;\n    }\n    return this.fragmentEnd;\n  }\n\n  get fragmentEnd(): number {\n    if (this.fragments?.length) {\n      return this.fragments[this.fragments.length - 1].end;\n    }\n    return 0;\n  }\n\n  get age(): number {\n    if (this.advancedDateTime) {\n      return Math.max(Date.now() - this.advancedDateTime, 0) / 1000;\n    }\n    return 0;\n  }\n\n  get lastPartIndex(): number {\n    if (this.partList?.length) {\n      return this.partList[this.partList.length - 1].index;\n    }\n    return -1;\n  }\n\n  get lastPartSn(): number {\n    if (this.partList?.length) {\n      return this.partList[this.partList.length - 1].fragment.sn as number;\n    }\n    return this.endSN;\n  }\n}\n", "export function base64ToBase64Url(base64encodedStr: string): string {\n  return base64encodedStr\n    .replace(/\\+/g, '-')\n    .replace(/\\//g, '_')\n    .replace(/=+$/, '');\n}\n\nexport function strToBase64Encode(str: string): string {\n  return btoa(str);\n}\n\nexport function base64DecodeToStr(str: string): string {\n  return atob(str);\n}\n\nexport function base64Encode(input: Uint8Array): string {\n  return btoa(String.fromCharCode(...input));\n}\n\nexport function base64UrlEncode(input: Uint8Array): string {\n  return base64ToBase64Url(base64Encode(input));\n}\n\nexport function base64Decode(base64encodedStr: string): Uint8Array {\n  return Uint8Array.from(atob(base64encodedStr), (c) => c.charCodeAt(0));\n}\n", "import { base64Decode } from './numeric-encoding-utils';\n\nfunction getKeyIdBytes(str: string): Uint8Array {\n  const keyIdbytes = strToUtf8array(str).subarray(0, 16);\n  const paddedkeyIdbytes = new Uint8Array(16);\n  paddedkeyIdbytes.set(keyIdbytes, 16 - keyIdbytes.length);\n  return paddedkeyIdbytes;\n}\n\nexport function changeEndianness(keyId: Uint8Array) {\n  const swap = function (array: Uint8Array, from: number, to: number) {\n    const cur = array[from];\n    array[from] = array[to];\n    array[to] = cur;\n  };\n\n  swap(keyId, 0, 3);\n  swap(keyId, 1, 2);\n  swap(keyId, 4, 5);\n  swap(keyId, 6, 7);\n}\n\nexport function convertDataUriToArrayBytes(uri: string): Uint8Array | null {\n  // data:[<media type][;attribute=value][;base64],<data>\n  const colonsplit = uri.split(':');\n  let keydata: Uint8Array | null = null;\n  if (colonsplit[0] === 'data' && colonsplit.length === 2) {\n    const semicolonsplit = colonsplit[1].split(';');\n    const commasplit = semicolonsplit[semicolonsplit.length - 1].split(',');\n    if (commasplit.length === 2) {\n      const isbase64 = commasplit[0] === 'base64';\n      const data = commasplit[1];\n      if (isbase64) {\n        semicolonsplit.splice(-1, 1); // remove from processing\n        keydata = base64Decode(data);\n      } else {\n        keydata = getKeyIdBytes(data);\n      }\n    }\n  }\n  return keydata;\n}\n\nexport function strToUtf8array(str: string): Uint8Array {\n  return Uint8Array.from(unescape(encodeURIComponent(str)), (c) =>\n    c.charCodeAt(0),\n  );\n}\n", "/** returns `undefined` is `self` is missing, e.g. in node */\nexport const optionalSelf = typeof self !== 'undefined' ? self : undefined;\n", "import type { DRMSystemOptions, EMEControllerConfig } from '../config';\nimport { optionalSelf } from './global';\n\n/**\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/requestMediaKeySystemAccess\n */\nexport const enum KeySystems {\n  CLEARKEY = 'org.w3.clearkey',\n  FAIRPLAY = 'com.apple.fps',\n  PLAYREADY = 'com.microsoft.playready',\n  WIDEVINE = 'com.widevine.alpha',\n}\n\n// Playlist #EXT-X-KEY KEYFORMAT values\nexport const enum KeySystemFormats {\n  CLEARKEY = 'org.w3.clearkey',\n  FAIRPLAY = 'com.apple.streamingkeydelivery',\n  PLAYREADY = 'com.microsoft.playready',\n  WIDEVINE = 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed',\n}\n\nexport function keySystemFormatToKeySystemDomain(\n  format: KeySystemFormats,\n): KeySystems | undefined {\n  switch (format) {\n    case KeySystemFormats.FAIRPLAY:\n      return KeySystems.FAIRPLAY;\n    case KeySystemFormats.PLAYREADY:\n      return KeySystems.PLAYREADY;\n    case KeySystemFormats.WIDEVINE:\n      return KeySystems.WIDEVINE;\n    case KeySystemFormats.CLEARKEY:\n      return KeySystems.CLEARKEY;\n  }\n}\n\n// System IDs for which we can extract a key ID from \"encrypted\" event PSSH\nexport const enum KeySystemIds {\n  CENC = '1077efecc0b24d02ace33c1e52e2fb4b',\n  CLEARKEY = 'e2719d58a985b3c9781ab030af78d30e',\n  FAIRPLAY = '94ce86fb07ff4f43adb893d2fa968ca2',\n  PLAYREADY = '9a04f07998404286ab92e65be0885f95',\n  WIDEVINE = 'edef8ba979d64acea3c827dcd51d21ed',\n}\n\nexport function keySystemIdToKeySystemDomain(\n  systemId: KeySystemIds,\n): KeySystems | undefined {\n  if (systemId === KeySystemIds.WIDEVINE) {\n    return KeySystems.WIDEVINE;\n  } else if (systemId === KeySystemIds.PLAYREADY) {\n    return KeySystems.PLAYREADY;\n  } else if (\n    systemId === KeySystemIds.CENC ||\n    systemId === KeySystemIds.CLEARKEY\n  ) {\n    return KeySystems.CLEARKEY;\n  }\n}\n\nexport function keySystemDomainToKeySystemFormat(\n  keySystem: KeySystems,\n): KeySystemFormats | undefined {\n  switch (keySystem) {\n    case KeySystems.FAIRPLAY:\n      return KeySystemFormats.FAIRPLAY;\n    case KeySystems.PLAYREADY:\n      return KeySystemFormats.PLAYREADY;\n    case KeySystems.WIDEVINE:\n      return KeySystemFormats.WIDEVINE;\n    case KeySystems.CLEARKEY:\n      return KeySystemFormats.CLEARKEY;\n  }\n}\n\nexport function getKeySystemsForConfig(\n  config: EMEControllerConfig,\n): KeySystems[] {\n  const { drmSystems, widevineLicenseUrl } = config;\n  const keySystemsToAttempt: KeySystems[] = drmSystems\n    ? [\n        KeySystems.FAIRPLAY,\n        KeySystems.WIDEVINE,\n        KeySystems.PLAYREADY,\n        KeySystems.CLEARKEY,\n      ].filter((keySystem) => !!drmSystems[keySystem])\n    : [];\n  if (!keySystemsToAttempt[KeySystems.WIDEVINE] && widevineLicenseUrl) {\n    keySystemsToAttempt.push(KeySystems.WIDEVINE);\n  }\n  return keySystemsToAttempt;\n}\n\nexport type MediaKeyFunc = (\n  keySystem: KeySystems,\n  supportedConfigurations: MediaKeySystemConfiguration[],\n) => Promise<MediaKeySystemAccess>;\n\nexport const requestMediaKeySystemAccess = (function (): MediaKeyFunc | null {\n  if (optionalSelf?.navigator?.requestMediaKeySystemAccess) {\n    return self.navigator.requestMediaKeySystemAccess.bind(self.navigator);\n  } else {\n    return null;\n  }\n})();\n\n/**\n * @see https://developer.mozilla.org/en-US/docs/Web/API/MediaKeySystemConfiguration\n */\nexport function getSupportedMediaKeySystemConfigurations(\n  keySystem: KeySystems,\n  audioCodecs: string[],\n  videoCodecs: string[],\n  drmSystemOptions: DRMSystemOptions,\n): MediaKeySystemConfiguration[] {\n  let initDataTypes: string[];\n  switch (keySystem) {\n    case KeySystems.FAIRPLAY:\n      initDataTypes = ['cenc', 'sinf'];\n      break;\n    case KeySystems.WIDEVINE:\n    case KeySystems.PLAYREADY:\n      initDataTypes = ['cenc'];\n      break;\n    case KeySystems.CLEARKEY:\n      initDataTypes = ['cenc', 'keyids'];\n      break;\n    default:\n      throw new Error(`Unknown key-system: ${keySystem}`);\n  }\n  return createMediaKeySystemConfigurations(\n    initDataTypes,\n    audioCodecs,\n    videoCodecs,\n    drmSystemOptions,\n  );\n}\n\nfunction createMediaKeySystemConfigurations(\n  initDataTypes: string[],\n  audioCodecs: string[],\n  videoCodecs: string[],\n  drmSystemOptions: DRMSystemOptions,\n): MediaKeySystemConfiguration[] {\n  const baseConfig: MediaKeySystemConfiguration = {\n    initDataTypes: initDataTypes,\n    persistentState: drmSystemOptions.persistentState || 'optional',\n    distinctiveIdentifier: drmSystemOptions.distinctiveIdentifier || 'optional',\n    sessionTypes: drmSystemOptions.sessionTypes || [\n      drmSystemOptions.sessionType || 'temporary',\n    ],\n    audioCapabilities: audioCodecs.map((codec) => ({\n      contentType: `audio/mp4; codecs=\"${codec}\"`,\n      robustness: drmSystemOptions.audioRobustness || '',\n      encryptionScheme: drmSystemOptions.audioEncryptionScheme || null,\n    })),\n    videoCapabilities: videoCodecs.map((codec) => ({\n      contentType: `video/mp4; codecs=\"${codec}\"`,\n      robustness: drmSystemOptions.videoRobustness || '',\n      encryptionScheme: drmSystemOptions.videoEncryptionScheme || null,\n    })),\n  };\n\n  return [baseConfig];\n}\n", "export function sliceUint8(\n  array: Uint8Array,\n  start?: number,\n  end?: number,\n): Uint8Array {\n  // @ts-expect-error This polyfills IE11 usage of Uint8Array slice.\n  // It always exists in the TypeScript definition so fails, but it fails at runtime on IE11.\n  return Uint8Array.prototype.slice\n    ? array.slice(start, end)\n    : new Uint8Array(Array.prototype.slice.call(array, start, end));\n}\n", "type RawFrame = { type: string; size: number; data: Uint8Array };\n\n// breaking up those two types in order to clarify what is happening in the decoding path.\ntype DecodedFrame<T> = { key: string; data: T; info?: any };\nexport type Frame = DecodedFrame<ArrayBuffer | string>;\n\n/**\n * Returns true if an ID3 header can be found at offset in data\n * @param data - The data to search\n * @param offset - The offset at which to start searching\n */\nexport const isHeader = (data: Uint8Array, offset: number): boolean => {\n  /*\n   * http://id3.org/id3v2.3.0\n   * [0]     = 'I'\n   * [1]     = 'D'\n   * [2]     = '3'\n   * [3,4]   = {Version}\n   * [5]     = {Flags}\n   * [6-9]   = {ID3 Size}\n   *\n   * An ID3v2 tag can be detected with the following pattern:\n   *  $49 44 33 yy yy xx zz zz zz zz\n   * Where yy is less than $FF, xx is the 'flags' byte and zz is less than $80\n   */\n  if (offset + 10 <= data.length) {\n    // look for 'ID3' identifier\n    if (\n      data[offset] === 0x49 &&\n      data[offset + 1] === 0x44 &&\n      data[offset + 2] === 0x33\n    ) {\n      // check version is within range\n      if (data[offset + 3] < 0xff && data[offset + 4] < 0xff) {\n        // check size is within range\n        if (\n          data[offset + 6] < 0x80 &&\n          data[offset + 7] < 0x80 &&\n          data[offset + 8] < 0x80 &&\n          data[offset + 9] < 0x80\n        ) {\n          return true;\n        }\n      }\n    }\n  }\n\n  return false;\n};\n\n/**\n * Returns true if an ID3 footer can be found at offset in data\n * @param data - The data to search\n * @param offset - The offset at which to start searching\n */\nexport const isFooter = (data: Uint8Array, offset: number): boolean => {\n  /*\n   * The footer is a copy of the header, but with a different identifier\n   */\n  if (offset + 10 <= data.length) {\n    // look for '3DI' identifier\n    if (\n      data[offset] === 0x33 &&\n      data[offset + 1] === 0x44 &&\n      data[offset + 2] === 0x49\n    ) {\n      // check version is within range\n      if (data[offset + 3] < 0xff && data[offset + 4] < 0xff) {\n        // check size is within range\n        if (\n          data[offset + 6] < 0x80 &&\n          data[offset + 7] < 0x80 &&\n          data[offset + 8] < 0x80 &&\n          data[offset + 9] < 0x80\n        ) {\n          return true;\n        }\n      }\n    }\n  }\n\n  return false;\n};\n\n/**\n * Returns any adjacent ID3 tags found in data starting at offset, as one block of data\n * @param data - The data to search in\n * @param offset - The offset at which to start searching\n * @returns the block of data containing any ID3 tags found\n * or *undefined* if no header is found at the starting offset\n */\nexport const getID3Data = (\n  data: Uint8Array,\n  offset: number,\n): Uint8Array | undefined => {\n  const front = offset;\n  let length = 0;\n\n  while (isHeader(data, offset)) {\n    // ID3 header is 10 bytes\n    length += 10;\n\n    const size = readSize(data, offset + 6);\n    length += size;\n\n    if (isFooter(data, offset + 10)) {\n      // ID3 footer is 10 bytes\n      length += 10;\n    }\n\n    offset += length;\n  }\n\n  if (length > 0) {\n    return data.subarray(front, front + length);\n  }\n\n  return undefined;\n};\n\nconst readSize = (data: Uint8Array, offset: number): number => {\n  let size = 0;\n  size = (data[offset] & 0x7f) << 21;\n  size |= (data[offset + 1] & 0x7f) << 14;\n  size |= (data[offset + 2] & 0x7f) << 7;\n  size |= data[offset + 3] & 0x7f;\n  return size;\n};\n\nexport const canParse = (data: Uint8Array, offset: number): boolean => {\n  return (\n    isHeader(data, offset) &&\n    readSize(data, offset + 6) + 10 <= data.length - offset\n  );\n};\n\n/**\n * Searches for the Elementary Stream timestamp found in the ID3 data chunk\n * @param data - Block of data containing one or more ID3 tags\n */\nexport const getTimeStamp = (data: Uint8Array): number | undefined => {\n  const frames: Frame[] = getID3Frames(data);\n\n  for (let i = 0; i < frames.length; i++) {\n    const frame = frames[i];\n\n    if (isTimeStampFrame(frame)) {\n      return readTimeStamp(frame as DecodedFrame<ArrayBuffer>);\n    }\n  }\n\n  return undefined;\n};\n\n/**\n * Returns true if the ID3 frame is an Elementary Stream timestamp frame\n */\nexport const isTimeStampFrame = (frame: Frame): boolean => {\n  return (\n    frame &&\n    frame.key === 'PRIV' &&\n    frame.info === 'com.apple.streaming.transportStreamTimestamp'\n  );\n};\n\nconst getFrameData = (data: Uint8Array): RawFrame => {\n  /*\n  Frame ID       $xx xx xx xx (four characters)\n  Size           $xx xx xx xx\n  Flags          $xx xx\n  */\n  const type: string = String.fromCharCode(data[0], data[1], data[2], data[3]);\n  const size: number = readSize(data, 4);\n\n  // skip frame id, size, and flags\n  const offset = 10;\n\n  return { type, size, data: data.subarray(offset, offset + size) };\n};\n\n/**\n * Returns an array of ID3 frames found in all the ID3 tags in the id3Data\n * @param id3Data - The ID3 data containing one or more ID3 tags\n */\nexport const getID3Frames = (id3Data: Uint8Array): Frame[] => {\n  let offset = 0;\n  const frames: Frame[] = [];\n\n  while (isHeader(id3Data, offset)) {\n    const size = readSize(id3Data, offset + 6);\n    // skip past ID3 header\n    offset += 10;\n    const end = offset + size;\n    // loop through frames in the ID3 tag\n    while (offset + 8 < end) {\n      const frameData: RawFrame = getFrameData(id3Data.subarray(offset));\n      const frame: Frame | undefined = decodeFrame(frameData);\n      if (frame) {\n        frames.push(frame);\n      }\n\n      // skip frame header and frame data\n      offset += frameData.size + 10;\n    }\n\n    if (isFooter(id3Data, offset)) {\n      offset += 10;\n    }\n  }\n\n  return frames;\n};\n\nexport const decodeFrame = (frame: RawFrame): Frame | undefined => {\n  if (frame.type === 'PRIV') {\n    return decodePrivFrame(frame);\n  } else if (frame.type[0] === 'W') {\n    return decodeURLFrame(frame);\n  }\n\n  return decodeTextFrame(frame);\n};\n\nconst decodePrivFrame = (\n  frame: RawFrame,\n): DecodedFrame<ArrayBuffer> | undefined => {\n  /*\n  Format: <text string>\\0<binary data>\n  */\n  if (frame.size < 2) {\n    return undefined;\n  }\n\n  const owner = utf8ArrayToStr(frame.data, true);\n  const privateData = new Uint8Array(frame.data.subarray(owner.length + 1));\n\n  return { key: frame.type, info: owner, data: privateData.buffer };\n};\n\nconst decodeTextFrame = (frame: RawFrame): DecodedFrame<string> | undefined => {\n  if (frame.size < 2) {\n    return undefined;\n  }\n\n  if (frame.type === 'TXXX') {\n    /*\n    Format:\n    [0]   = {Text Encoding}\n    [1-?] = {Description}\\0{Value}\n    */\n    let index = 1;\n    const description = utf8ArrayToStr(frame.data.subarray(index), true);\n\n    index += description.length + 1;\n    const value = utf8ArrayToStr(frame.data.subarray(index));\n\n    return { key: frame.type, info: description, data: value };\n  }\n  /*\n  Format:\n  [0]   = {Text Encoding}\n  [1-?] = {Value}\n  */\n  const text = utf8ArrayToStr(frame.data.subarray(1));\n  return { key: frame.type, data: text };\n};\n\nconst decodeURLFrame = (frame: RawFrame): DecodedFrame<string> | undefined => {\n  if (frame.type === 'WXXX') {\n    /*\n    Format:\n    [0]   = {Text Encoding}\n    [1-?] = {Description}\\0{URL}\n    */\n    if (frame.size < 2) {\n      return undefined;\n    }\n\n    let index = 1;\n    const description: string = utf8ArrayToStr(\n      frame.data.subarray(index),\n      true,\n    );\n\n    index += description.length + 1;\n    const value: string = utf8ArrayToStr(frame.data.subarray(index));\n\n    return { key: frame.type, info: description, data: value };\n  }\n  /*\n  Format:\n  [0-?] = {URL}\n  */\n  const url: string = utf8ArrayToStr(frame.data);\n  return { key: frame.type, data: url };\n};\n\nconst readTimeStamp = (\n  timeStampFrame: DecodedFrame<ArrayBuffer>,\n): number | undefined => {\n  if (timeStampFrame.data.byteLength === 8) {\n    const data = new Uint8Array(timeStampFrame.data);\n    // timestamp is 33 bit expressed as a big-endian eight-octet number,\n    // with the upper 31 bits set to zero.\n    const pts33Bit = data[3] & 0x1;\n    let timestamp =\n      (data[4] << 23) + (data[5] << 15) + (data[6] << 7) + data[7];\n    timestamp /= 45;\n\n    if (pts33Bit) {\n      timestamp += 47721858.84;\n    } // 2^32 / 90\n\n    return Math.round(timestamp);\n  }\n\n  return undefined;\n};\n\n// http://stackoverflow.com/questions/8936984/uint8array-to-string-in-javascript/22373197\n// http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt\n/* utf.js - UTF-8 <=> UTF-16 convertion\n *\n * Copyright (C) 1999 Masanao Izumo <iz@onicos.co.jp>\n * Version: 1.0\n * LastModified: Dec 25 1999\n * This library is free.  You can redistribute it and/or modify it.\n */\nexport const utf8ArrayToStr = (\n  array: Uint8Array,\n  exitOnNull: boolean = false,\n): string => {\n  const decoder = getTextDecoder();\n  if (decoder) {\n    const decoded = decoder.decode(array);\n\n    if (exitOnNull) {\n      // grab up to the first null\n      const idx = decoded.indexOf('\\0');\n      return idx !== -1 ? decoded.substring(0, idx) : decoded;\n    }\n\n    // remove any null characters\n    return decoded.replace(/\\0/g, '');\n  }\n\n  const len = array.length;\n  let c;\n  let char2;\n  let char3;\n  let out = '';\n  let i = 0;\n  while (i < len) {\n    c = array[i++];\n    if (c === 0x00 && exitOnNull) {\n      return out;\n    } else if (c === 0x00 || c === 0x03) {\n      // If the character is 3 (END_OF_TEXT) or 0 (NULL) then skip it\n      continue;\n    }\n    switch (c >> 4) {\n      case 0:\n      case 1:\n      case 2:\n      case 3:\n      case 4:\n      case 5:\n      case 6:\n      case 7:\n        // 0xxxxxxx\n        out += String.fromCharCode(c);\n        break;\n      case 12:\n      case 13:\n        // 110x xxxx   10xx xxxx\n        char2 = array[i++];\n        out += String.fromCharCode(((c & 0x1f) << 6) | (char2 & 0x3f));\n        break;\n      case 14:\n        // 1110 xxxx  10xx xxxx  10xx xxxx\n        char2 = array[i++];\n        char3 = array[i++];\n        out += String.fromCharCode(\n          ((c & 0x0f) << 12) | ((char2 & 0x3f) << 6) | ((char3 & 0x3f) << 0),\n        );\n        break;\n      default:\n    }\n  }\n  return out;\n};\n\nexport const testables = {\n  decodeTextFrame: decodeTextFrame,\n};\n\nlet decoder: TextDecoder;\n\nfunction getTextDecoder() {\n  // On Play Station 4, TextDecoder is defined but partially implemented.\n  // Manual decoding option is preferable\n  if (navigator.userAgent.includes('PlayStation 4')) {\n    return;\n  }\n\n  if (!decoder && typeof self.TextDecoder !== 'undefined') {\n    decoder = new self.TextDecoder('utf-8');\n  }\n\n  return decoder;\n}\n", "/**\n *  hex dump helper class\n */\n\nconst Hex = {\n  hexDump: function (array: Uint8Array) {\n    let str = '';\n    for (let i = 0; i < array.length; i++) {\n      let h = array[i].toString(16);\n      if (h.length < 2) {\n        h = '0' + h;\n      }\n\n      str += h;\n    }\n    return str;\n  },\n};\n\nexport default Hex;\n", "import { ElementaryStreamTypes } from '../loader/fragment';\nimport { sliceUint8 } from './typed-array';\nimport { utf8ArrayToStr } from '../demux/id3';\nimport { logger } from '../utils/logger';\nimport Hex from './hex';\nimport type { KeySystemIds } from './mediakeys-helper';\nimport type { PassthroughTrack, UserdataSample } from '../types/demuxer';\nimport type { DecryptData } from '../loader/level-key';\n\nconst UINT32_MAX = Math.pow(2, 32) - 1;\nconst push = [].push;\n\n// We are using fixed track IDs for driving the MP4 remuxer\n// instead of following the TS PIDs.\n// There is no reason not to do this and some browsers/SourceBuffer-demuxers\n// may not like if there are TrackID \"switches\"\n// See https://github.com/video-dev/hls.js/issues/1331\n// Here we are mapping our internal track types to constant MP4 track IDs\n// With MSE currently one can only have one track of each, and we are muxing\n// whatever video/audio rendition in them.\nexport const RemuxerTrackIdConfig = {\n  video: 1,\n  audio: 2,\n  id3: 3,\n  text: 4,\n};\n\nexport function bin2str(data: Uint8Array): string {\n  return String.fromCharCode.apply(null, data);\n}\n\nexport function readUint16(buffer: Uint8Array, offset: number): number {\n  const val = (buffer[offset] << 8) | buffer[offset + 1];\n  return val < 0 ? 65536 + val : val;\n}\n\nexport function readUint32(buffer: Uint8Array, offset: number): number {\n  const val = readSint32(buffer, offset);\n  return val < 0 ? 4294967296 + val : val;\n}\n\nexport function readUint64(buffer: Uint8Array, offset: number) {\n  let result = readUint32(buffer, offset);\n  result *= Math.pow(2, 32);\n  result += readUint32(buffer, offset + 4);\n  return result;\n}\n\nexport function readSint32(buffer: Uint8Array, offset: number): number {\n  return (\n    (buffer[offset] << 24) |\n    (buffer[offset + 1] << 16) |\n    (buffer[offset + 2] << 8) |\n    buffer[offset + 3]\n  );\n}\n\nexport function writeUint32(buffer: Uint8Array, offset: number, value: number) {\n  buffer[offset] = value >> 24;\n  buffer[offset + 1] = (value >> 16) & 0xff;\n  buffer[offset + 2] = (value >> 8) & 0xff;\n  buffer[offset + 3] = value & 0xff;\n}\n\n// Find \"moof\" box\nexport function hasMoofData(data: Uint8Array): boolean {\n  const end = data.byteLength;\n  for (let i = 0; i < end; ) {\n    const size = readUint32(data, i);\n    if (\n      size > 8 &&\n      data[i + 4] === 0x6d &&\n      data[i + 5] === 0x6f &&\n      data[i + 6] === 0x6f &&\n      data[i + 7] === 0x66\n    ) {\n      return true;\n    }\n    i = size > 1 ? i + size : end;\n  }\n  return false;\n}\n\n// Find the data for a box specified by its path\nexport function findBox(data: Uint8Array, path: string[]): Uint8Array[] {\n  const results = [] as Uint8Array[];\n  if (!path.length) {\n    // short-circuit the search for empty paths\n    return results;\n  }\n  const end = data.byteLength;\n\n  for (let i = 0; i < end; ) {\n    const size = readUint32(data, i);\n    const type = bin2str(data.subarray(i + 4, i + 8));\n    const endbox = size > 1 ? i + size : end;\n    if (type === path[0]) {\n      if (path.length === 1) {\n        // this is the end of the path and we've found the box we were\n        // looking for\n        results.push(data.subarray(i + 8, endbox));\n      } else {\n        // recursively search for the next box along the path\n        const subresults = findBox(data.subarray(i + 8, endbox), path.slice(1));\n        if (subresults.length) {\n          push.apply(results, subresults);\n        }\n      }\n    }\n    i = endbox;\n  }\n\n  // we've finished searching all of data\n  return results;\n}\n\ntype SidxInfo = {\n  earliestPresentationTime: number;\n  timescale: number;\n  version: number;\n  referencesCount: number;\n  references: any[];\n};\n\nexport function parseSegmentIndex(sidx: Uint8Array): SidxInfo | null {\n  const references: any[] = [];\n\n  const version = sidx[0];\n\n  // set initial offset, we skip the reference ID (not needed)\n  let index = 8;\n\n  const timescale = readUint32(sidx, index);\n  index += 4;\n\n  let earliestPresentationTime = 0;\n  let firstOffset = 0;\n\n  if (version === 0) {\n    earliestPresentationTime = readUint32(sidx, index);\n    firstOffset = readUint32(sidx, index + 4);\n    index += 8;\n  } else {\n    earliestPresentationTime = readUint64(sidx, index);\n    firstOffset = readUint64(sidx, index + 8);\n    index += 16;\n  }\n\n  // skip reserved\n  index += 2;\n\n  let startByte = sidx.length + firstOffset;\n\n  const referencesCount = readUint16(sidx, index);\n  index += 2;\n\n  for (let i = 0; i < referencesCount; i++) {\n    let referenceIndex = index;\n\n    const referenceInfo = readUint32(sidx, referenceIndex);\n    referenceIndex += 4;\n\n    const referenceSize = referenceInfo & 0x7fffffff;\n    const referenceType = (referenceInfo & 0x80000000) >>> 31;\n\n    if (referenceType === 1) {\n      logger.warn('SIDX has hierarchical references (not supported)');\n      return null;\n    }\n\n    const subsegmentDuration = readUint32(sidx, referenceIndex);\n    referenceIndex += 4;\n\n    references.push({\n      referenceSize,\n      subsegmentDuration, // unscaled\n      info: {\n        duration: subsegmentDuration / timescale,\n        start: startByte,\n        end: startByte + referenceSize - 1,\n      },\n    });\n\n    startByte += referenceSize;\n\n    // Skipping 1 bit for |startsWithSap|, 3 bits for |sapType|, and 28 bits\n    // for |sapDelta|.\n    referenceIndex += 4;\n\n    // skip to next ref\n    index = referenceIndex;\n  }\n\n  return {\n    earliestPresentationTime,\n    timescale,\n    version,\n    referencesCount,\n    references,\n  };\n}\n\n/**\n * Parses an MP4 initialization segment and extracts stream type and\n * timescale values for any declared tracks. Timescale values indicate the\n * number of clock ticks per second to assume for time-based values\n * elsewhere in the MP4.\n *\n * To determine the start time of an MP4, you need two pieces of\n * information: the timescale unit and the earliest base media decode\n * time. Multiple timescales can be specified within an MP4 but the\n * base media decode time is always expressed in the timescale from\n * the media header box for the track:\n * ```\n * moov > trak > mdia > mdhd.timescale\n * moov > trak > mdia > hdlr\n * ```\n * @param initSegment the bytes of the init segment\n * @returns a hash of track type to timescale values or null if\n * the init segment is malformed.\n */\n\nexport interface InitDataTrack {\n  timescale: number;\n  id: number;\n  codec: string;\n}\n\ntype HdlrType = ElementaryStreamTypes.AUDIO | ElementaryStreamTypes.VIDEO;\n\nexport interface InitData extends Array<any> {\n  [index: number]:\n    | {\n        timescale: number;\n        type: HdlrType;\n        default?: {\n          duration: number;\n          flags: number;\n        };\n      }\n    | undefined;\n  audio?: InitDataTrack;\n  video?: InitDataTrack;\n  caption?: InitDataTrack;\n}\n\nexport function parseInitSegment(initSegment: Uint8Array): InitData {\n  const result: InitData = [];\n  const traks = findBox(initSegment, ['moov', 'trak']);\n  for (let i = 0; i < traks.length; i++) {\n    const trak = traks[i];\n    const tkhd = findBox(trak, ['tkhd'])[0];\n    if (tkhd) {\n      let version = tkhd[0];\n      const trackId = readUint32(tkhd, version === 0 ? 12 : 20);\n      const mdhd = findBox(trak, ['mdia', 'mdhd'])[0];\n      if (mdhd) {\n        version = mdhd[0];\n        const timescale = readUint32(mdhd, version === 0 ? 12 : 20);\n        const hdlr = findBox(trak, ['mdia', 'hdlr'])[0];\n        if (hdlr) {\n          const hdlrType = bin2str(hdlr.subarray(8, 12));\n          const type: HdlrType | undefined = {\n            soun: ElementaryStreamTypes.AUDIO as const,\n            vide: ElementaryStreamTypes.VIDEO as const,\n          }[hdlrType];\n          if (type) {\n            // Parse codec details\n            const stsd = findBox(trak, ['mdia', 'minf', 'stbl', 'stsd'])[0];\n            const stsdData = parseStsd(stsd);\n            result[trackId] = { timescale, type };\n            result[type] = { timescale, id: trackId, ...stsdData };\n          }\n        }\n      }\n    }\n  }\n\n  const trex = findBox(initSegment, ['moov', 'mvex', 'trex']);\n  trex.forEach((trex) => {\n    const trackId = readUint32(trex, 4);\n    const track = result[trackId];\n    if (track) {\n      track.default = {\n        duration: readUint32(trex, 12),\n        flags: readUint32(trex, 20),\n      };\n    }\n  });\n\n  return result;\n}\n\nfunction parseStsd(stsd: Uint8Array): { codec: string; encrypted: boolean } {\n  const sampleEntries = stsd.subarray(8);\n  const sampleEntriesEnd = sampleEntries.subarray(8 + 78);\n  const fourCC = bin2str(sampleEntries.subarray(4, 8));\n  let codec = fourCC;\n  const encrypted = fourCC === 'enca' || fourCC === 'encv';\n  if (encrypted) {\n    const encBox = findBox(sampleEntries, [fourCC])[0];\n    const encBoxChildren = encBox.subarray(fourCC === 'enca' ? 28 : 78);\n    const sinfs = findBox(encBoxChildren, ['sinf']);\n    sinfs.forEach((sinf) => {\n      const schm = findBox(sinf, ['schm'])[0];\n      if (schm) {\n        const scheme = bin2str(schm.subarray(4, 8));\n        if (scheme === 'cbcs' || scheme === 'cenc') {\n          const frma = findBox(sinf, ['frma'])[0];\n          if (frma) {\n            // for encrypted content codec fourCC will be in frma\n            codec = bin2str(frma);\n          }\n        }\n      }\n    });\n  }\n  switch (codec) {\n    case 'avc1':\n    case 'avc2':\n    case 'avc3':\n    case 'avc4': {\n      // extract profile + compatibility + level out of avcC box\n      const avcCBox = findBox(sampleEntriesEnd, ['avcC'])[0];\n      codec += '.' + toHex(avcCBox[1]) + toHex(avcCBox[2]) + toHex(avcCBox[3]);\n      break;\n    }\n    case 'mp4a': {\n      const codecBox = findBox(sampleEntries, [fourCC])[0];\n      const esdsBox = findBox(codecBox.subarray(28), ['esds'])[0];\n      if (esdsBox && esdsBox.length > 12) {\n        let i = 4;\n        // ES Descriptor tag\n        if (esdsBox[i++] !== 0x03) {\n          break;\n        }\n        i = skipBERInteger(esdsBox, i);\n        i += 2; // skip es_id;\n        const flags = esdsBox[i++];\n        if (flags & 0x80) {\n          i += 2; // skip dependency es_id\n        }\n        if (flags & 0x40) {\n          i += esdsBox[i++]; // skip URL\n        }\n        // Decoder config descriptor\n        if (esdsBox[i++] !== 0x04) {\n          break;\n        }\n        i = skipBERInteger(esdsBox, i);\n        const objectType = esdsBox[i++];\n        if (objectType === 0x40) {\n          codec += '.' + toHex(objectType);\n        } else {\n          break;\n        }\n        i += 12;\n        // Decoder specific info\n        if (esdsBox[i++] !== 0x05) {\n          break;\n        }\n        i = skipBERInteger(esdsBox, i);\n        const firstByte = esdsBox[i++];\n        let audioObjectType = (firstByte & 0xf8) >> 3;\n        if (audioObjectType === 31) {\n          audioObjectType +=\n            1 + ((firstByte & 0x7) << 3) + ((esdsBox[i] & 0xe0) >> 5);\n        }\n        codec += '.' + audioObjectType;\n      }\n      break;\n    }\n    case 'hvc1':\n    case 'hev1': {\n      const hvcCBox = findBox(sampleEntriesEnd, ['hvcC'])[0];\n      const profileByte = hvcCBox[1];\n      const profileSpace = ['', 'A', 'B', 'C'][profileByte >> 6];\n      const generalProfileIdc = profileByte & 0x1f;\n      const profileCompat = readUint32(hvcCBox, 2);\n      const tierFlag = (profileByte & 0x20) >> 5 ? 'H' : 'L';\n      const levelIDC = hvcCBox[12];\n      const constraintIndicator = hvcCBox.subarray(6, 12);\n      codec += '.' + profileSpace + generalProfileIdc;\n      codec += '.' + profileCompat.toString(16).toUpperCase();\n      codec += '.' + tierFlag + levelIDC;\n      let constraintString = '';\n      for (let i = constraintIndicator.length; i--; ) {\n        const byte = constraintIndicator[i];\n        if (byte || constraintString) {\n          const encodedByte = byte.toString(16).toUpperCase();\n          constraintString = '.' + encodedByte + constraintString;\n        }\n      }\n      codec += constraintString;\n      break;\n    }\n    case 'dvh1':\n    case 'dvhe': {\n      const dvcCBox = findBox(sampleEntriesEnd, ['dvcC'])[0];\n      const profile = (dvcCBox[2] >> 1) & 0x7f;\n      const level = ((dvcCBox[2] << 5) & 0x20) | ((dvcCBox[3] >> 3) & 0x1f);\n      codec += '.' + addLeadingZero(profile) + '.' + addLeadingZero(level);\n      break;\n    }\n    case 'vp09': {\n      const vpcCBox = findBox(sampleEntriesEnd, ['vpcC'])[0];\n      const profile = vpcCBox[4];\n      const level = vpcCBox[5];\n      const bitDepth = (vpcCBox[6] >> 4) & 0x0f;\n      codec +=\n        '.' +\n        addLeadingZero(profile) +\n        '.' +\n        addLeadingZero(level) +\n        '.' +\n        addLeadingZero(bitDepth);\n      break;\n    }\n    case 'av01': {\n      const av1CBox = findBox(sampleEntriesEnd, ['av1C'])[0];\n      const profile = av1CBox[1] >>> 5;\n      const level = av1CBox[1] & 0x1f;\n      const tierFlag = av1CBox[2] >>> 7 ? 'H' : 'M';\n      const highBitDepth = (av1CBox[2] & 0x40) >> 6;\n      const twelveBit = (av1CBox[2] & 0x20) >> 5;\n      const bitDepth =\n        profile === 2 && highBitDepth\n          ? twelveBit\n            ? 12\n            : 10\n          : highBitDepth\n            ? 10\n            : 8;\n      const monochrome = (av1CBox[2] & 0x10) >> 4;\n      const chromaSubsamplingX = (av1CBox[2] & 0x08) >> 3;\n      const chromaSubsamplingY = (av1CBox[2] & 0x04) >> 2;\n      const chromaSamplePosition = av1CBox[2] & 0x03;\n      // TODO: parse color_description_present_flag\n      // default it to BT.709/limited range for now\n      // more info https://aomediacodec.github.io/av1-isobmff/#av1codecconfigurationbox-syntax\n      const colorPrimaries = 1;\n      const transferCharacteristics = 1;\n      const matrixCoefficients = 1;\n      const videoFullRangeFlag = 0;\n      codec +=\n        '.' +\n        profile +\n        '.' +\n        addLeadingZero(level) +\n        tierFlag +\n        '.' +\n        addLeadingZero(bitDepth) +\n        '.' +\n        monochrome +\n        '.' +\n        chromaSubsamplingX +\n        chromaSubsamplingY +\n        chromaSamplePosition +\n        '.' +\n        addLeadingZero(colorPrimaries) +\n        '.' +\n        addLeadingZero(transferCharacteristics) +\n        '.' +\n        addLeadingZero(matrixCoefficients) +\n        '.' +\n        videoFullRangeFlag;\n      break;\n    }\n    case 'ac-3':\n    case 'ec-3':\n    case 'alac':\n    case 'fLaC':\n    case 'Opus':\n    default:\n      break;\n  }\n  return { codec, encrypted };\n}\n\nfunction skipBERInteger(bytes: Uint8Array, i: number): number {\n  const limit = i + 5;\n  while (bytes[i++] & 0x80 && i < limit) {}\n  return i;\n}\n\nfunction toHex(x: number): string {\n  return ('0' + x.toString(16).toUpperCase()).slice(-2);\n}\n\nfunction addLeadingZero(num: number): string {\n  return (num < 10 ? '0' : '') + num;\n}\n\nexport function patchEncyptionData(\n  initSegment: Uint8Array | undefined,\n  decryptdata: DecryptData | null,\n): Uint8Array | undefined {\n  if (!initSegment || !decryptdata) {\n    return initSegment;\n  }\n  const keyId = decryptdata.keyId;\n  if (keyId && decryptdata.isCommonEncryption) {\n    const traks = findBox(initSegment, ['moov', 'trak']);\n    traks.forEach((trak) => {\n      const stsd = findBox(trak, ['mdia', 'minf', 'stbl', 'stsd'])[0];\n\n      // skip the sample entry count\n      const sampleEntries = stsd.subarray(8);\n      let encBoxes = findBox(sampleEntries, ['enca']);\n      const isAudio = encBoxes.length > 0;\n      if (!isAudio) {\n        encBoxes = findBox(sampleEntries, ['encv']);\n      }\n      encBoxes.forEach((enc) => {\n        const encBoxChildren = isAudio ? enc.subarray(28) : enc.subarray(78);\n        const sinfBoxes = findBox(encBoxChildren, ['sinf']);\n        sinfBoxes.forEach((sinf) => {\n          const tenc = parseSinf(sinf);\n          if (tenc) {\n            // Look for default key id (keyID offset is always 8 within the tenc box):\n            const tencKeyId = tenc.subarray(8, 24);\n            if (!tencKeyId.some((b) => b !== 0)) {\n              logger.log(\n                `[eme] Patching keyId in 'enc${\n                  isAudio ? 'a' : 'v'\n                }>sinf>>tenc' box: ${Hex.hexDump(tencKeyId)} -> ${Hex.hexDump(\n                  keyId,\n                )}`,\n              );\n              tenc.set(keyId, 8);\n            }\n          }\n        });\n      });\n    });\n  }\n\n  return initSegment;\n}\n\nexport function parseSinf(sinf: Uint8Array): Uint8Array | null {\n  const schm = findBox(sinf, ['schm'])[0];\n  if (schm) {\n    const scheme = bin2str(schm.subarray(4, 8));\n    if (scheme === 'cbcs' || scheme === 'cenc') {\n      return findBox(sinf, ['schi', 'tenc'])[0];\n    }\n  }\n  return null;\n}\n\n/**\n * Determine the base media decode start time, in seconds, for an MP4\n * fragment. If multiple fragments are specified, the earliest time is\n * returned.\n *\n * The base media decode time can be parsed from track fragment\n * metadata:\n * ```\n * moof > traf > tfdt.baseMediaDecodeTime\n * ```\n * It requires the timescale value from the mdhd to interpret.\n *\n * @param initData - a hash of track type to timescale values\n * @param fmp4 - the bytes of the mp4 fragment\n * @returns the earliest base media decode start time for the\n * fragment, in seconds\n */\nexport function getStartDTS(\n  initData: InitData,\n  fmp4: Uint8Array,\n): number | null {\n  // we need info from two children of each track fragment box\n  return findBox(fmp4, ['moof', 'traf']).reduce(\n    (result: number | null, traf) => {\n      const tfdt = findBox(traf, ['tfdt'])[0];\n      const version = tfdt[0];\n      const start = findBox(traf, ['tfhd']).reduce(\n        (result: number | null, tfhd) => {\n          // get the track id from the tfhd\n          const id = readUint32(tfhd, 4);\n          const track = initData[id];\n          if (track) {\n            let baseTime = readUint32(tfdt, 4);\n            if (version === 1) {\n              // If value is too large, assume signed 64-bit. Negative track fragment decode times are invalid, but they exist in the wild.\n              // This prevents large values from being used for initPTS, which can cause playlist sync issues.\n              // https://github.com/video-dev/hls.js/issues/5303\n              if (baseTime === UINT32_MAX) {\n                logger.warn(\n                  `[mp4-demuxer]: Ignoring assumed invalid signed 64-bit track fragment decode time`,\n                );\n                return result;\n              }\n              baseTime *= UINT32_MAX + 1;\n              baseTime += readUint32(tfdt, 8);\n            }\n            // assume a 90kHz clock if no timescale was specified\n            const scale = track.timescale || 90e3;\n            // convert base time to seconds\n            const startTime = baseTime / scale;\n            if (\n              Number.isFinite(startTime) &&\n              (result === null || startTime < result)\n            ) {\n              return startTime;\n            }\n          }\n          return result;\n        },\n        null,\n      );\n      if (\n        start !== null &&\n        Number.isFinite(start) &&\n        (result === null || start < result)\n      ) {\n        return start;\n      }\n      return result;\n    },\n    null,\n  );\n}\n\n/*\n  For Reference:\n  aligned(8) class TrackFragmentHeaderBox\n           extends FullBox(\u2018tfhd\u2019, 0, tf_flags){\n     unsigned int(32)  track_ID;\n     // all the following are optional fields\n     unsigned int(64)  base_data_offset;\n     unsigned int(32)  sample_description_index;\n     unsigned int(32)  default_sample_duration;\n     unsigned int(32)  default_sample_size;\n     unsigned int(32)  default_sample_flags\n  }\n */\nexport function getDuration(data: Uint8Array, initData: InitData) {\n  let rawDuration = 0;\n  let videoDuration = 0;\n  let audioDuration = 0;\n  const trafs = findBox(data, ['moof', 'traf']);\n  for (let i = 0; i < trafs.length; i++) {\n    const traf = trafs[i];\n    // There is only one tfhd & trun per traf\n    // This is true for CMAF style content, and we should perhaps check the ftyp\n    // and only look for a single trun then, but for ISOBMFF we should check\n    // for multiple track runs.\n    const tfhd = findBox(traf, ['tfhd'])[0];\n    // get the track id from the tfhd\n    const id = readUint32(tfhd, 4);\n    const track = initData[id];\n    if (!track) {\n      continue;\n    }\n    const trackDefault = track.default;\n    const tfhdFlags = readUint32(tfhd, 0) | trackDefault?.flags!;\n    let sampleDuration: number | undefined = trackDefault?.duration;\n    if (tfhdFlags & 0x000008) {\n      // 0x000008 indicates the presence of the default_sample_duration field\n      if (tfhdFlags & 0x000002) {\n        // 0x000002 indicates the presence of the sample_description_index field, which precedes default_sample_duration\n        // If present, the default_sample_duration exists at byte offset 12\n        sampleDuration = readUint32(tfhd, 12);\n      } else {\n        // Otherwise, the duration is at byte offset 8\n        sampleDuration = readUint32(tfhd, 8);\n      }\n    }\n    // assume a 90kHz clock if no timescale was specified\n    const timescale = track.timescale || 90e3;\n    const truns = findBox(traf, ['trun']);\n    for (let j = 0; j < truns.length; j++) {\n      rawDuration = computeRawDurationFromSamples(truns[j]);\n      if (!rawDuration && sampleDuration) {\n        const sampleCount = readUint32(truns[j], 4);\n        rawDuration = sampleDuration * sampleCount;\n      }\n      if (track.type === ElementaryStreamTypes.VIDEO) {\n        videoDuration += rawDuration / timescale;\n      } else if (track.type === ElementaryStreamTypes.AUDIO) {\n        audioDuration += rawDuration / timescale;\n      }\n    }\n  }\n  if (videoDuration === 0 && audioDuration === 0) {\n    // If duration samples are not available in the traf use sidx subsegment_duration\n    let sidxMinStart = Infinity;\n    let sidxMaxEnd = 0;\n    let sidxDuration = 0;\n    const sidxs = findBox(data, ['sidx']);\n    for (let i = 0; i < sidxs.length; i++) {\n      const sidx = parseSegmentIndex(sidxs[i]);\n      if (sidx?.references) {\n        sidxMinStart = Math.min(\n          sidxMinStart,\n          sidx.earliestPresentationTime / sidx.timescale,\n        );\n        const subSegmentDuration = sidx.references.reduce(\n          (dur, ref) => dur + ref.info.duration || 0,\n          0,\n        );\n        sidxMaxEnd = Math.max(\n          sidxMaxEnd,\n          subSegmentDuration + sidx.earliestPresentationTime / sidx.timescale,\n        );\n        sidxDuration = sidxMaxEnd - sidxMinStart;\n      }\n    }\n    if (sidxDuration && Number.isFinite(sidxDuration)) {\n      return sidxDuration;\n    }\n  }\n  if (videoDuration) {\n    return videoDuration;\n  }\n  return audioDuration;\n}\n\n/*\n  For Reference:\n  aligned(8) class TrackRunBox\n           extends FullBox(\u2018trun\u2019, version, tr_flags) {\n     unsigned int(32)  sample_count;\n     // the following are optional fields\n     signed int(32) data_offset;\n     unsigned int(32)  first_sample_flags;\n     // all fields in the following array are optional\n     {\n        unsigned int(32)  sample_duration;\n        unsigned int(32)  sample_size;\n        unsigned int(32)  sample_flags\n        if (version == 0)\n           { unsigned int(32)\n        else\n           { signed int(32)\n     }[ sample_count ]\n  }\n */\nexport function computeRawDurationFromSamples(trun): number {\n  const flags = readUint32(trun, 0);\n  // Flags are at offset 0, non-optional sample_count is at offset 4. Therefore we start 8 bytes in.\n  // Each field is an int32, which is 4 bytes\n  let offset = 8;\n  // data-offset-present flag\n  if (flags & 0x000001) {\n    offset += 4;\n  }\n  // first-sample-flags-present flag\n  if (flags & 0x000004) {\n    offset += 4;\n  }\n\n  let duration = 0;\n  const sampleCount = readUint32(trun, 4);\n  for (let i = 0; i < sampleCount; i++) {\n    // sample-duration-present flag\n    if (flags & 0x000100) {\n      const sampleDuration = readUint32(trun, offset);\n      duration += sampleDuration;\n      offset += 4;\n    }\n    // sample-size-present flag\n    if (flags & 0x000200) {\n      offset += 4;\n    }\n    // sample-flags-present flag\n    if (flags & 0x000400) {\n      offset += 4;\n    }\n    // sample-composition-time-offsets-present flag\n    if (flags & 0x000800) {\n      offset += 4;\n    }\n  }\n  return duration;\n}\n\nexport function offsetStartDTS(\n  initData: InitData,\n  fmp4: Uint8Array,\n  timeOffset: number,\n) {\n  findBox(fmp4, ['moof', 'traf']).forEach((traf) => {\n    findBox(traf, ['tfhd']).forEach((tfhd) => {\n      // get the track id from the tfhd\n      const id = readUint32(tfhd, 4);\n      const track = initData[id];\n      if (!track) {\n        return;\n      }\n      // assume a 90kHz clock if no timescale was specified\n      const timescale = track.timescale || 90e3;\n      // get the base media decode time from the tfdt\n      findBox(traf, ['tfdt']).forEach((tfdt) => {\n        const version = tfdt[0];\n        const offset = timeOffset * timescale;\n        if (offset) {\n          let baseMediaDecodeTime = readUint32(tfdt, 4);\n          if (version === 0) {\n            baseMediaDecodeTime -= offset;\n            baseMediaDecodeTime = Math.max(baseMediaDecodeTime, 0);\n            writeUint32(tfdt, 4, baseMediaDecodeTime);\n          } else {\n            baseMediaDecodeTime *= Math.pow(2, 32);\n            baseMediaDecodeTime += readUint32(tfdt, 8);\n            baseMediaDecodeTime -= offset;\n            baseMediaDecodeTime = Math.max(baseMediaDecodeTime, 0);\n            const upper = Math.floor(baseMediaDecodeTime / (UINT32_MAX + 1));\n            const lower = Math.floor(baseMediaDecodeTime % (UINT32_MAX + 1));\n            writeUint32(tfdt, 4, upper);\n            writeUint32(tfdt, 8, lower);\n          }\n        }\n      });\n    });\n  });\n}\n\n// TODO: Check if the last moof+mdat pair is part of the valid range\nexport function segmentValidRange(data: Uint8Array): SegmentedRange {\n  const segmentedRange: SegmentedRange = {\n    valid: null,\n    remainder: null,\n  };\n\n  const moofs = findBox(data, ['moof']);\n  if (moofs.length < 2) {\n    segmentedRange.remainder = data;\n    return segmentedRange;\n  }\n  const last = moofs[moofs.length - 1];\n  // Offset by 8 bytes; findBox offsets the start by as much\n  segmentedRange.valid = sliceUint8(data, 0, last.byteOffset - 8);\n  segmentedRange.remainder = sliceUint8(data, last.byteOffset - 8);\n  return segmentedRange;\n}\n\nexport interface SegmentedRange {\n  valid: Uint8Array | null;\n  remainder: Uint8Array | null;\n}\n\nexport function appendUint8Array(\n  data1: Uint8Array,\n  data2: Uint8Array,\n): Uint8Array {\n  const temp = new Uint8Array(data1.length + data2.length);\n  temp.set(data1);\n  temp.set(data2, data1.length);\n\n  return temp;\n}\n\nexport interface IEmsgParsingData {\n  schemeIdUri: string;\n  value: string;\n  timeScale: number;\n  presentationTimeDelta?: number;\n  presentationTime?: number;\n  eventDuration: number;\n  id: number;\n  payload: Uint8Array;\n}\n\nexport function parseSamples(\n  timeOffset: number,\n  track: PassthroughTrack,\n): UserdataSample[] {\n  const seiSamples = [] as UserdataSample[];\n  const videoData = track.samples;\n  const timescale = track.timescale;\n  const trackId = track.id;\n  let isHEVCFlavor = false;\n\n  const moofs = findBox(videoData, ['moof']);\n  moofs.map((moof) => {\n    const moofOffset = moof.byteOffset - 8;\n    const trafs = findBox(moof, ['traf']);\n    trafs.map((traf) => {\n      // get the base media decode time from the tfdt\n      const baseTime = findBox(traf, ['tfdt']).map((tfdt) => {\n        const version = tfdt[0];\n        let result = readUint32(tfdt, 4);\n        if (version === 1) {\n          result *= Math.pow(2, 32);\n          result += readUint32(tfdt, 8);\n        }\n        return result / timescale;\n      })[0];\n\n      if (baseTime !== undefined) {\n        timeOffset = baseTime;\n      }\n\n      return findBox(traf, ['tfhd']).map((tfhd) => {\n        const id = readUint32(tfhd, 4);\n        const tfhdFlags = readUint32(tfhd, 0) & 0xffffff;\n        const baseDataOffsetPresent = (tfhdFlags & 0x000001) !== 0;\n        const sampleDescriptionIndexPresent = (tfhdFlags & 0x000002) !== 0;\n        const defaultSampleDurationPresent = (tfhdFlags & 0x000008) !== 0;\n        let defaultSampleDuration = 0;\n        const defaultSampleSizePresent = (tfhdFlags & 0x000010) !== 0;\n        let defaultSampleSize = 0;\n        const defaultSampleFlagsPresent = (tfhdFlags & 0x000020) !== 0;\n        let tfhdOffset = 8;\n\n        if (id === trackId) {\n          if (baseDataOffsetPresent) {\n            tfhdOffset += 8;\n          }\n          if (sampleDescriptionIndexPresent) {\n            tfhdOffset += 4;\n          }\n          if (defaultSampleDurationPresent) {\n            defaultSampleDuration = readUint32(tfhd, tfhdOffset);\n            tfhdOffset += 4;\n          }\n          if (defaultSampleSizePresent) {\n            defaultSampleSize = readUint32(tfhd, tfhdOffset);\n            tfhdOffset += 4;\n          }\n          if (defaultSampleFlagsPresent) {\n            tfhdOffset += 4;\n          }\n          if (track.type === 'video') {\n            isHEVCFlavor = isHEVC(track.codec);\n          }\n\n          findBox(traf, ['trun']).map((trun) => {\n            const version = trun[0];\n            const flags = readUint32(trun, 0) & 0xffffff;\n            const dataOffsetPresent = (flags & 0x000001) !== 0;\n            let dataOffset = 0;\n            const firstSampleFlagsPresent = (flags & 0x000004) !== 0;\n            const sampleDurationPresent = (flags & 0x000100) !== 0;\n            let sampleDuration = 0;\n            const sampleSizePresent = (flags & 0x000200) !== 0;\n            let sampleSize = 0;\n            const sampleFlagsPresent = (flags & 0x000400) !== 0;\n            const sampleCompositionOffsetsPresent = (flags & 0x000800) !== 0;\n            let compositionOffset = 0;\n            const sampleCount = readUint32(trun, 4);\n            let trunOffset = 8; // past version, flags, and sample count\n\n            if (dataOffsetPresent) {\n              dataOffset = readUint32(trun, trunOffset);\n              trunOffset += 4;\n            }\n            if (firstSampleFlagsPresent) {\n              trunOffset += 4;\n            }\n\n            let sampleOffset = dataOffset + moofOffset;\n\n            for (let ix = 0; ix < sampleCount; ix++) {\n              if (sampleDurationPresent) {\n                sampleDuration = readUint32(trun, trunOffset);\n                trunOffset += 4;\n              } else {\n                sampleDuration = defaultSampleDuration;\n              }\n              if (sampleSizePresent) {\n                sampleSize = readUint32(trun, trunOffset);\n                trunOffset += 4;\n              } else {\n                sampleSize = defaultSampleSize;\n              }\n              if (sampleFlagsPresent) {\n                trunOffset += 4;\n              }\n              if (sampleCompositionOffsetsPresent) {\n                if (version === 0) {\n                  compositionOffset = readUint32(trun, trunOffset);\n                } else {\n                  compositionOffset = readSint32(trun, trunOffset);\n                }\n                trunOffset += 4;\n              }\n              if (track.type === ElementaryStreamTypes.VIDEO) {\n                let naluTotalSize = 0;\n                while (naluTotalSize < sampleSize) {\n                  const naluSize = readUint32(videoData, sampleOffset);\n                  sampleOffset += 4;\n                  if (isSEIMessage(isHEVCFlavor, videoData[sampleOffset])) {\n                    const data = videoData.subarray(\n                      sampleOffset,\n                      sampleOffset + naluSize,\n                    );\n                    parseSEIMessageFromNALu(\n                      data,\n                      isHEVCFlavor ? 2 : 1,\n                      timeOffset + compositionOffset / timescale,\n                      seiSamples,\n                    );\n                  }\n                  sampleOffset += naluSize;\n                  naluTotalSize += naluSize + 4;\n                }\n              }\n\n              timeOffset += sampleDuration / timescale;\n            }\n          });\n        }\n      });\n    });\n  });\n  return seiSamples;\n}\n\nfunction isHEVC(codec: string) {\n  if (!codec) {\n    return false;\n  }\n  const delimit = codec.indexOf('.');\n  const baseCodec = delimit < 0 ? codec : codec.substring(0, delimit);\n  return (\n    baseCodec === 'hvc1' ||\n    baseCodec === 'hev1' ||\n    // Dolby Vision\n    baseCodec === 'dvh1' ||\n    baseCodec === 'dvhe'\n  );\n}\n\nfunction isSEIMessage(isHEVCFlavor: boolean, naluHeader: number) {\n  if (isHEVCFlavor) {\n    const naluType = (naluHeader >> 1) & 0x3f;\n    return naluType === 39 || naluType === 40;\n  } else {\n    const naluType = naluHeader & 0x1f;\n    return naluType === 6;\n  }\n}\n\nexport function parseSEIMessageFromNALu(\n  unescapedData: Uint8Array,\n  headerSize: number,\n  pts: number,\n  samples: UserdataSample[],\n) {\n  const data = discardEPB(unescapedData);\n  let seiPtr = 0;\n  // skip nal header\n  seiPtr += headerSize;\n  let payloadType = 0;\n  let payloadSize = 0;\n  let b = 0;\n\n  while (seiPtr < data.length) {\n    payloadType = 0;\n    do {\n      if (seiPtr >= data.length) {\n        break;\n      }\n      b = data[seiPtr++];\n      payloadType += b;\n    } while (b === 0xff);\n\n    // Parse payload size.\n    payloadSize = 0;\n    do {\n      if (seiPtr >= data.length) {\n        break;\n      }\n      b = data[seiPtr++];\n      payloadSize += b;\n    } while (b === 0xff);\n\n    const leftOver = data.length - seiPtr;\n    // Create a variable to process the payload\n    let payPtr = seiPtr;\n\n    // Increment the seiPtr to the end of the payload\n    if (payloadSize < leftOver) {\n      seiPtr += payloadSize;\n    } else if (payloadSize > leftOver) {\n      // Some type of corruption has happened?\n      logger.error(\n        `Malformed SEI payload. ${payloadSize} is too small, only ${leftOver} bytes left to parse.`,\n      );\n      // We might be able to parse some data, but let's be safe and ignore it.\n      break;\n    }\n\n    if (payloadType === 4) {\n      const countryCode = data[payPtr++];\n      if (countryCode === 181) {\n        const providerCode = readUint16(data, payPtr);\n        payPtr += 2;\n\n        if (providerCode === 49) {\n          const userStructure = readUint32(data, payPtr);\n          payPtr += 4;\n\n          if (userStructure === 0x47413934) {\n            const userDataType = data[payPtr++];\n\n            // Raw CEA-608 bytes wrapped in CEA-708 packet\n            if (userDataType === 3) {\n              const firstByte = data[payPtr++];\n              const totalCCs = 0x1f & firstByte;\n              const enabled = 0x40 & firstByte;\n              const totalBytes = enabled ? 2 + totalCCs * 3 : 0;\n              const byteArray = new Uint8Array(totalBytes);\n              if (enabled) {\n                byteArray[0] = firstByte;\n                for (let i = 1; i < totalBytes; i++) {\n                  byteArray[i] = data[payPtr++];\n                }\n              }\n\n              samples.push({\n                type: userDataType,\n                payloadType,\n                pts,\n                bytes: byteArray,\n              });\n            }\n          }\n        }\n      }\n    } else if (payloadType === 5) {\n      if (payloadSize > 16) {\n        const uuidStrArray: Array<string> = [];\n        for (let i = 0; i < 16; i++) {\n          const b = data[payPtr++].toString(16);\n          uuidStrArray.push(b.length == 1 ? '0' + b : b);\n\n          if (i === 3 || i === 5 || i === 7 || i === 9) {\n            uuidStrArray.push('-');\n          }\n        }\n        const length = payloadSize - 16;\n        const userDataBytes = new Uint8Array(length);\n        for (let i = 0; i < length; i++) {\n          userDataBytes[i] = data[payPtr++];\n        }\n\n        samples.push({\n          payloadType,\n          pts,\n          uuid: uuidStrArray.join(''),\n          userData: utf8ArrayToStr(userDataBytes),\n          userDataBytes,\n        });\n      }\n    }\n  }\n}\n\n/**\n * remove Emulation Prevention bytes from a RBSP\n */\nexport function discardEPB(data: Uint8Array): Uint8Array {\n  const length = data.byteLength;\n  const EPBPositions = [] as Array<number>;\n  let i = 1;\n\n  // Find all `Emulation Prevention Bytes`\n  while (i < length - 2) {\n    if (data[i] === 0 && data[i + 1] === 0 && data[i + 2] === 0x03) {\n      EPBPositions.push(i + 2);\n      i += 2;\n    } else {\n      i++;\n    }\n  }\n\n  // If no Emulation Prevention Bytes were found just return the original\n  // array\n  if (EPBPositions.length === 0) {\n    return data;\n  }\n\n  // Create a new array to hold the NAL unit data\n  const newLength = length - EPBPositions.length;\n  const newData = new Uint8Array(newLength);\n  let sourceIndex = 0;\n\n  for (i = 0; i < newLength; sourceIndex++, i++) {\n    if (sourceIndex === EPBPositions[0]) {\n      // Skip this byte\n      sourceIndex++;\n      // Remove this position index\n      EPBPositions.shift();\n    }\n    newData[i] = data[sourceIndex];\n  }\n  return newData;\n}\n\nexport function parseEmsg(data: Uint8Array): IEmsgParsingData {\n  const version = data[0];\n  let schemeIdUri: string = '';\n  let value: string = '';\n  let timeScale: number = 0;\n  let presentationTimeDelta: number = 0;\n  let presentationTime: number = 0;\n  let eventDuration: number = 0;\n  let id: number = 0;\n  let offset: number = 0;\n\n  if (version === 0) {\n    while (bin2str(data.subarray(offset, offset + 1)) !== '\\0') {\n      schemeIdUri += bin2str(data.subarray(offset, offset + 1));\n      offset += 1;\n    }\n\n    schemeIdUri += bin2str(data.subarray(offset, offset + 1));\n    offset += 1;\n\n    while (bin2str(data.subarray(offset, offset + 1)) !== '\\0') {\n      value += bin2str(data.subarray(offset, offset + 1));\n      offset += 1;\n    }\n\n    value += bin2str(data.subarray(offset, offset + 1));\n    offset += 1;\n\n    timeScale = readUint32(data, 12);\n    presentationTimeDelta = readUint32(data, 16);\n    eventDuration = readUint32(data, 20);\n    id = readUint32(data, 24);\n    offset = 28;\n  } else if (version === 1) {\n    offset += 4;\n    timeScale = readUint32(data, offset);\n    offset += 4;\n    const leftPresentationTime = readUint32(data, offset);\n    offset += 4;\n    const rightPresentationTime = readUint32(data, offset);\n    offset += 4;\n    presentationTime = 2 ** 32 * leftPresentationTime + rightPresentationTime;\n    if (!Number.isSafeInteger(presentationTime)) {\n      presentationTime = Number.MAX_SAFE_INTEGER;\n      logger.warn(\n        'Presentation time exceeds safe integer limit and wrapped to max safe integer in parsing emsg box',\n      );\n    }\n\n    eventDuration = readUint32(data, offset);\n    offset += 4;\n    id = readUint32(data, offset);\n    offset += 4;\n\n    while (bin2str(data.subarray(offset, offset + 1)) !== '\\0') {\n      schemeIdUri += bin2str(data.subarray(offset, offset + 1));\n      offset += 1;\n    }\n\n    schemeIdUri += bin2str(data.subarray(offset, offset + 1));\n    offset += 1;\n\n    while (bin2str(data.subarray(offset, offset + 1)) !== '\\0') {\n      value += bin2str(data.subarray(offset, offset + 1));\n      offset += 1;\n    }\n\n    value += bin2str(data.subarray(offset, offset + 1));\n    offset += 1;\n  }\n  const payload = data.subarray(offset, data.byteLength);\n\n  return {\n    schemeIdUri,\n    value,\n    timeScale,\n    presentationTime,\n    presentationTimeDelta,\n    eventDuration,\n    id,\n    payload,\n  };\n}\n\nexport function mp4Box(type: ArrayLike<number>, ...payload: Uint8Array[]) {\n  const len = payload.length;\n  let size = 8;\n  let i = len;\n  while (i--) {\n    size += payload[i].byteLength;\n  }\n  const result = new Uint8Array(size);\n  result[0] = (size >> 24) & 0xff;\n  result[1] = (size >> 16) & 0xff;\n  result[2] = (size >> 8) & 0xff;\n  result[3] = size & 0xff;\n  result.set(type, 4);\n  for (i = 0, size = 8; i < len; i++) {\n    result.set(payload[i], size);\n    size += payload[i].byteLength;\n  }\n  return result;\n}\n\nexport function mp4pssh(\n  systemId: Uint8Array,\n  keyids: Array<Uint8Array> | null,\n  data: Uint8Array,\n) {\n  if (systemId.byteLength !== 16) {\n    throw new RangeError('Invalid system id');\n  }\n  let version;\n  let kids;\n  if (keyids) {\n    version = 1;\n    kids = new Uint8Array(keyids.length * 16);\n    for (let ix = 0; ix < keyids.length; ix++) {\n      const k = keyids[ix]; // uint8array\n      if (k.byteLength !== 16) {\n        throw new RangeError('Invalid key');\n      }\n      kids.set(k, ix * 16);\n    }\n  } else {\n    version = 0;\n    kids = new Uint8Array();\n  }\n  let kidCount;\n  if (version > 0) {\n    kidCount = new Uint8Array(4);\n    if (keyids!.length > 0) {\n      new DataView(kidCount.buffer).setUint32(0, keyids!.length, false);\n    }\n  } else {\n    kidCount = new Uint8Array();\n  }\n  const dataSize = new Uint8Array(4);\n  if (data && data.byteLength > 0) {\n    new DataView(dataSize.buffer).setUint32(0, data.byteLength, false);\n  }\n  return mp4Box(\n    [112, 115, 115, 104],\n    new Uint8Array([\n      version,\n      0x00,\n      0x00,\n      0x00, // Flags\n    ]),\n    systemId, // 16 bytes\n    kidCount,\n    kids,\n    dataSize,\n    data || new Uint8Array(),\n  );\n}\n\nexport type PsshData = {\n  version: 0 | 1;\n  systemId: KeySystemIds;\n  kids: null | Uint8Array[];\n  data: null | Uint8Array;\n  offset: number;\n  size: number;\n};\n\nexport type PsshInvalidResult = {\n  systemId?: undefined;\n  offset: number;\n  size: number;\n};\n\nexport function parseMultiPssh(\n  initData: ArrayBuffer,\n): (PsshData | PsshInvalidResult)[] {\n  const results: (PsshData | PsshInvalidResult)[] = [];\n  if (initData instanceof ArrayBuffer) {\n    const length = initData.byteLength;\n    let offset = 0;\n    while (offset + 32 < length) {\n      const view = new DataView(initData, offset);\n      const pssh = parsePssh(view);\n      results.push(pssh);\n      offset += pssh.size;\n    }\n  }\n  return results;\n}\n\nfunction parsePssh(view: DataView): PsshData | PsshInvalidResult {\n  const size = view.getUint32(0);\n  const offset = view.byteOffset;\n  const length = view.byteLength;\n  if (length < size) {\n    return {\n      offset,\n      size: length,\n    };\n  }\n  const type = view.getUint32(4);\n  if (type !== 0x70737368) {\n    return { offset, size };\n  }\n  const version = view.getUint32(8) >>> 24;\n  if (version !== 0 && version !== 1) {\n    return { offset, size };\n  }\n  const buffer = view.buffer;\n  const systemId = Hex.hexDump(\n    new Uint8Array(buffer, offset + 12, 16),\n  ) as KeySystemIds;\n  const dataSizeOrKidCount = view.getUint32(28);\n  let kids: null | Uint8Array[] = null;\n  let data: null | Uint8Array = null;\n  if (version === 0) {\n    if (size - 32 < dataSizeOrKidCount || dataSizeOrKidCount < 22) {\n      return { offset, size };\n    }\n    data = new Uint8Array(buffer, offset + 32, dataSizeOrKidCount);\n  } else if (version === 1) {\n    if (\n      !dataSizeOrKidCount ||\n      length < offset + 32 + dataSizeOrKidCount * 16 + 16\n    ) {\n      return { offset, size };\n    }\n    kids = [];\n    for (let i = 0; i < dataSizeOrKidCount; i++) {\n      kids.push(new Uint8Array(buffer, offset + 32 + i * 16, 16));\n    }\n  }\n  return {\n    version,\n    systemId,\n    kids,\n    data,\n    offset,\n    size,\n  };\n}\n", "import {\n  changeEndianness,\n  convertDataUriToArrayBytes,\n} from '../utils/keysystem-util';\nimport { KeySystemFormats } from '../utils/mediakeys-helper';\nimport { mp4pssh } from '../utils/mp4-tools';\nimport { logger } from '../utils/logger';\nimport { base64Decode } from '../utils/numeric-encoding-utils';\n\nlet keyUriToKeyIdMap: { [uri: string]: Uint8Array } = {};\n\nexport interface DecryptData {\n  uri: string;\n  method: string;\n  keyFormat: string;\n  keyFormatVersions: number[];\n  iv: Uint8Array | null;\n  key: Uint8Array | null;\n  keyId: Uint8Array | null;\n  pssh: Uint8Array | null;\n  encrypted: boolean;\n  isCommonEncryption: boolean;\n}\n\nexport class LevelKey implements DecryptData {\n  public readonly uri: string;\n  public readonly method: string;\n  public readonly keyFormat: string;\n  public readonly keyFormatVersions: number[];\n  public readonly encrypted: boolean;\n  public readonly isCommonEncryption: boolean;\n  public iv: Uint8Array | null = null;\n  public key: Uint8Array | null = null;\n  public keyId: Uint8Array | null = null;\n  public pssh: Uint8Array | null = null;\n\n  static clearKeyUriToKeyIdMap() {\n    keyUriToKeyIdMap = {};\n  }\n\n  constructor(\n    method: string,\n    uri: string,\n    format: string,\n    formatversions: number[] = [1],\n    iv: Uint8Array | null = null,\n  ) {\n    this.method = method;\n    this.uri = uri;\n    this.keyFormat = format;\n    this.keyFormatVersions = formatversions;\n    this.iv = iv;\n    this.encrypted = method ? method !== 'NONE' : false;\n    this.isCommonEncryption = this.encrypted && method !== 'AES-128';\n  }\n\n  public isSupported(): boolean {\n    // If it's Segment encryption or No encryption, just select that key system\n    if (this.method) {\n      if (this.method === 'AES-128' || this.method === 'NONE') {\n        return true;\n      }\n      if (this.keyFormat === 'identity') {\n        // Maintain support for clear SAMPLE-AES with MPEG-3 TS\n        return this.method === 'SAMPLE-AES';\n      } else if (__USE_EME_DRM__) {\n        switch (this.keyFormat) {\n          case KeySystemFormats.FAIRPLAY:\n          case KeySystemFormats.WIDEVINE:\n          case KeySystemFormats.PLAYREADY:\n          case KeySystemFormats.CLEARKEY:\n            return (\n              [\n                'ISO-23001-7',\n                'SAMPLE-AES',\n                'SAMPLE-AES-CENC',\n                'SAMPLE-AES-CTR',\n              ].indexOf(this.method) !== -1\n            );\n        }\n      }\n    }\n    return false;\n  }\n\n  public getDecryptData(sn: number | 'initSegment'): LevelKey | null {\n    if (!this.encrypted || !this.uri) {\n      return null;\n    }\n\n    if (this.method === 'AES-128' && this.uri && !this.iv) {\n      if (typeof sn !== 'number') {\n        // We are fetching decryption data for a initialization segment\n        // If the segment was encrypted with AES-128\n        // It must have an IV defined. We cannot substitute the Segment Number in.\n        if (this.method === 'AES-128' && !this.iv) {\n          logger.warn(\n            `missing IV for initialization segment with method=\"${this.method}\" - compliance issue`,\n          );\n        }\n        // Explicitly set sn to resulting value from implicit conversions 'initSegment' values for IV generation.\n        sn = 0;\n      }\n      const iv = createInitializationVector(sn);\n      const decryptdata = new LevelKey(\n        this.method,\n        this.uri,\n        'identity',\n        this.keyFormatVersions,\n        iv,\n      );\n      return decryptdata;\n    }\n\n    if (!__USE_EME_DRM__) {\n      return this;\n    }\n\n    // Initialize keyId if possible\n    const keyBytes = convertDataUriToArrayBytes(this.uri);\n    if (keyBytes) {\n      switch (this.keyFormat) {\n        case KeySystemFormats.WIDEVINE:\n          this.pssh = keyBytes;\n          // In case of widevine keyID is embedded in PSSH box. Read Key ID.\n          if (keyBytes.length >= 22) {\n            this.keyId = keyBytes.subarray(\n              keyBytes.length - 22,\n              keyBytes.length - 6,\n            );\n          }\n          break;\n        case KeySystemFormats.PLAYREADY: {\n          const PlayReadyKeySystemUUID = new Uint8Array([\n            0x9a, 0x04, 0xf0, 0x79, 0x98, 0x40, 0x42, 0x86, 0xab, 0x92, 0xe6,\n            0x5b, 0xe0, 0x88, 0x5f, 0x95,\n          ]);\n\n          this.pssh = mp4pssh(PlayReadyKeySystemUUID, null, keyBytes);\n\n          const keyBytesUtf16 = new Uint16Array(\n            keyBytes.buffer,\n            keyBytes.byteOffset,\n            keyBytes.byteLength / 2,\n          );\n          const keyByteStr = String.fromCharCode.apply(\n            null,\n            Array.from(keyBytesUtf16),\n          );\n\n          // Parse Playready WRMHeader XML\n          const xmlKeyBytes = keyByteStr.substring(\n            keyByteStr.indexOf('<'),\n            keyByteStr.length,\n          );\n          const parser = new DOMParser();\n          const xmlDoc = parser.parseFromString(xmlKeyBytes, 'text/xml');\n          const keyData = xmlDoc.getElementsByTagName('KID')[0];\n          if (keyData) {\n            const keyId = keyData.childNodes[0]\n              ? keyData.childNodes[0].nodeValue\n              : keyData.getAttribute('VALUE');\n            if (keyId) {\n              const keyIdArray = base64Decode(keyId).subarray(0, 16);\n              // KID value in PRO is a base64-encoded little endian GUID interpretation of UUID\n              // KID value in \u2018tenc\u2019 is a big endian UUID GUID interpretation of UUID\n              changeEndianness(keyIdArray);\n              this.keyId = keyIdArray;\n            }\n          }\n          break;\n        }\n        default: {\n          let keydata = keyBytes.subarray(0, 16);\n          if (keydata.length !== 16) {\n            const padded = new Uint8Array(16);\n            padded.set(keydata, 16 - keydata.length);\n            keydata = padded;\n          }\n          this.keyId = keydata;\n          break;\n        }\n      }\n    }\n\n    // Default behavior: assign a new keyId for each uri\n    if (!this.keyId || this.keyId.byteLength !== 16) {\n      let keyId = keyUriToKeyIdMap[this.uri];\n      if (!keyId) {\n        const val =\n          Object.keys(keyUriToKeyIdMap).length % Number.MAX_SAFE_INTEGER;\n        keyId = new Uint8Array(16);\n        const dv = new DataView(keyId.buffer, 12, 4); // Just set the last 4 bytes\n        dv.setUint32(0, val);\n        keyUriToKeyIdMap[this.uri] = keyId;\n      }\n      this.keyId = keyId;\n    }\n\n    return this;\n  }\n}\n\nfunction createInitializationVector(segmentNumber: number): Uint8Array {\n  const uint8View = new Uint8Array(16);\n  for (let i = 12; i < 16; i++) {\n    uint8View[i] = (segmentNumber >> (8 * (15 - i))) & 0xff;\n  }\n  return uint8View;\n}\n", "import type { AttrList } from './attr-list';\nimport type { ParsedMultivariantPlaylist } from '../loader/m3u8-parser';\nimport type { LevelDetails } from '../loader/level-details';\nimport type { VariableMap } from '../types/level';\n\nconst VARIABLE_REPLACEMENT_REGEX = /\\{\\$([a-zA-Z0-9-_]+)\\}/g;\n\nexport function hasVariableReferences(str: string): boolean {\n  return VARIABLE_REPLACEMENT_REGEX.test(str);\n}\n\nexport function substituteVariablesInAttributes(\n  parsed: Pick<\n    ParsedMultivariantPlaylist | LevelDetails,\n    'variableList' | 'hasVariableRefs' | 'playlistParsingError'\n  >,\n  attr: AttrList,\n  attributeNames: string[],\n) {\n  if (parsed.variableList !== null || parsed.hasVariableRefs) {\n    for (let i = attributeNames.length; i--; ) {\n      const name = attributeNames[i];\n      const value = attr[name];\n      if (value) {\n        attr[name] = substituteVariables(parsed, value);\n      }\n    }\n  }\n}\n\nexport function substituteVariables(\n  parsed: Pick<\n    ParsedMultivariantPlaylist | LevelDetails,\n    'variableList' | 'hasVariableRefs' | 'playlistParsingError'\n  >,\n  value: string,\n): string {\n  if (parsed.variableList !== null || parsed.hasVariableRefs) {\n    const variableList = parsed.variableList;\n    return value.replace(\n      VARIABLE_REPLACEMENT_REGEX,\n      (variableReference: string) => {\n        const variableName = variableReference.substring(\n          2,\n          variableReference.length - 1,\n        );\n        const variableValue = variableList?.[variableName];\n        if (variableValue === undefined) {\n          parsed.playlistParsingError ||= new Error(\n            `Missing preceding EXT-X-DEFINE tag for Variable Reference: \"${variableName}\"`,\n          );\n          return variableReference;\n        }\n        return variableValue;\n      },\n    );\n  }\n  return value;\n}\n\nexport function addVariableDefinition(\n  parsed: Pick<\n    ParsedMultivariantPlaylist | LevelDetails,\n    'variableList' | 'playlistParsingError'\n  >,\n  attr: AttrList,\n  parentUrl: string,\n) {\n  let variableList = parsed.variableList;\n  if (!variableList) {\n    parsed.variableList = variableList = {};\n  }\n  let NAME: string;\n  let VALUE;\n  if ('QUERYPARAM' in attr) {\n    NAME = attr.QUERYPARAM;\n    try {\n      const searchParams = new self.URL(parentUrl).searchParams;\n      if (searchParams.has(NAME)) {\n        VALUE = searchParams.get(NAME);\n      } else {\n        throw new Error(\n          `\"${NAME}\" does not match any query parameter in URI: \"${parentUrl}\"`,\n        );\n      }\n    } catch (error) {\n      parsed.playlistParsingError ||= new Error(\n        `EXT-X-DEFINE QUERYPARAM: ${error.message}`,\n      );\n    }\n  } else {\n    NAME = attr.NAME;\n    VALUE = attr.VALUE;\n  }\n  if (NAME in variableList) {\n    parsed.playlistParsingError ||= new Error(\n      `EXT-X-DEFINE duplicate Variable Name declarations: \"${NAME}\"`,\n    );\n  } else {\n    variableList[NAME] = VALUE || '';\n  }\n}\n\nexport function importVariableDefinition(\n  parsed: Pick<\n    ParsedMultivariantPlaylist | LevelDetails,\n    'variableList' | 'playlistParsingError'\n  >,\n  attr: AttrList,\n  sourceVariableList: VariableMap | null,\n) {\n  const IMPORT = attr.IMPORT;\n  if (sourceVariableList && IMPORT in sourceVariableList) {\n    let variableList = parsed.variableList;\n    if (!variableList) {\n      parsed.variableList = variableList = {};\n    }\n    variableList[IMPORT] = sourceVariableList[IMPORT];\n  } else {\n    parsed.playlistParsingError ||= new Error(\n      `EXT-X-DEFINE IMPORT attribute not found in Multivariant Playlist: \"${IMPORT}\"`,\n    );\n  }\n}\n", "/**\n * MediaSource helper\n */\n\nexport function getMediaSource(\n  preferManagedMediaSource = true,\n): typeof MediaSource | undefined {\n  if (typeof self === 'undefined') return undefined;\n  const mms =\n    (preferManagedMediaSource || !self.MediaSource) &&\n    ((self as any).ManagedMediaSource as undefined | typeof MediaSource);\n  return (\n    mms ||\n    self.MediaSource ||\n    ((self as any).WebKitMediaSource as typeof MediaSource)\n  );\n}\n\nexport function isManagedMediaSource(source: typeof MediaSource | undefined) {\n  return (\n    typeof self !== 'undefined' && source === (self as any).ManagedMediaSource\n  );\n}\n", "import { getMediaSource } from './mediasource-helper';\n\n// from http://mp4ra.org/codecs.html\n// values indicate codec selection preference (lower is higher priority)\nconst sampleEntryCodesISO = {\n  audio: {\n    a3ds: 1,\n    'ac-3': 0.95,\n    'ac-4': 1,\n    alac: 0.9,\n    alaw: 1,\n    dra1: 1,\n    'dts+': 1,\n    'dts-': 1,\n    dtsc: 1,\n    dtse: 1,\n    dtsh: 1,\n    'ec-3': 0.9,\n    enca: 1,\n    fLaC: 0.9, // MP4-RA listed codec entry for FLAC\n    flac: 0.9, // legacy browser codec name for FLAC\n    FLAC: 0.9, // some manifests may list \"FLAC\" with Apple's tools\n    g719: 1,\n    g726: 1,\n    m4ae: 1,\n    mha1: 1,\n    mha2: 1,\n    mhm1: 1,\n    mhm2: 1,\n    mlpa: 1,\n    mp4a: 1,\n    'raw ': 1,\n    Opus: 1,\n    opus: 1, // browsers expect this to be lowercase despite MP4RA says 'Opus'\n    samr: 1,\n    sawb: 1,\n    sawp: 1,\n    sevc: 1,\n    sqcp: 1,\n    ssmv: 1,\n    twos: 1,\n    ulaw: 1,\n  },\n  video: {\n    avc1: 1,\n    avc2: 1,\n    avc3: 1,\n    avc4: 1,\n    avcp: 1,\n    av01: 0.8,\n    drac: 1,\n    dva1: 1,\n    dvav: 1,\n    dvh1: 0.7,\n    dvhe: 0.7,\n    encv: 1,\n    hev1: 0.75,\n    hvc1: 0.75,\n    mjp2: 1,\n    mp4v: 1,\n    mvc1: 1,\n    mvc2: 1,\n    mvc3: 1,\n    mvc4: 1,\n    resv: 1,\n    rv60: 1,\n    s263: 1,\n    svc1: 1,\n    svc2: 1,\n    'vc-1': 1,\n    vp08: 1,\n    vp09: 0.9,\n  },\n  text: {\n    stpp: 1,\n    wvtt: 1,\n  },\n} as const;\n\nexport type CodecType = 'audio' | 'video';\n\nexport function isCodecType(codec: string, type: CodecType): boolean {\n  const typeCodes = sampleEntryCodesISO[type];\n  return !!typeCodes && !!typeCodes[codec.slice(0, 4)];\n}\n\nexport function areCodecsMediaSourceSupported(\n  codecs: string,\n  type: CodecType,\n  preferManagedMediaSource = true,\n): boolean {\n  return !codecs\n    .split(',')\n    .some(\n      (codec) =>\n        !isCodecMediaSourceSupported(codec, type, preferManagedMediaSource),\n    );\n}\n\nfunction isCodecMediaSourceSupported(\n  codec: string,\n  type: CodecType,\n  preferManagedMediaSource = true,\n): boolean {\n  const MediaSource = getMediaSource(preferManagedMediaSource);\n  return MediaSource?.isTypeSupported(mimeTypeForCodec(codec, type)) ?? false;\n}\n\nexport function mimeTypeForCodec(codec: string, type: CodecType): string {\n  return `${type}/mp4;codecs=\"${codec}\"`;\n}\n\nexport function videoCodecPreferenceValue(\n  videoCodec: string | undefined,\n): number {\n  if (videoCodec) {\n    const fourCC = videoCodec.substring(0, 4);\n    return sampleEntryCodesISO.video[fourCC];\n  }\n  return 2;\n}\n\nexport function codecsSetSelectionPreferenceValue(codecSet: string): number {\n  return codecSet.split(',').reduce((num, fourCC) => {\n    const preferenceValue = sampleEntryCodesISO.video[fourCC];\n    if (preferenceValue) {\n      return (preferenceValue * 2 + num) / (num ? 3 : 2);\n    }\n    return (sampleEntryCodesISO.audio[fourCC] + num) / (num ? 2 : 1);\n  }, 0);\n}\n\ninterface CodecNameCache {\n  flac?: string;\n  opus?: string;\n}\n\nconst CODEC_COMPATIBLE_NAMES: CodecNameCache = {};\n\ntype LowerCaseCodecType = 'flac' | 'opus';\n\nfunction getCodecCompatibleNameLower(\n  lowerCaseCodec: LowerCaseCodecType,\n  preferManagedMediaSource = true,\n): string {\n  if (CODEC_COMPATIBLE_NAMES[lowerCaseCodec]) {\n    return CODEC_COMPATIBLE_NAMES[lowerCaseCodec]!;\n  }\n\n  // Idealy fLaC and Opus would be first (spec-compliant) but\n  // some browsers will report that fLaC is supported then fail.\n  // see: https://bugs.chromium.org/p/chromium/issues/detail?id=1422728\n  const codecsToCheck = {\n    flac: ['flac', 'fLaC', 'FLAC'],\n    opus: ['opus', 'Opus'],\n  }[lowerCaseCodec];\n\n  for (let i = 0; i < codecsToCheck.length; i++) {\n    if (\n      isCodecMediaSourceSupported(\n        codecsToCheck[i],\n        'audio',\n        preferManagedMediaSource,\n      )\n    ) {\n      CODEC_COMPATIBLE_NAMES[lowerCaseCodec] = codecsToCheck[i];\n      return codecsToCheck[i];\n    }\n  }\n\n  return lowerCaseCodec;\n}\n\nconst AUDIO_CODEC_REGEXP = /flac|opus/i;\nexport function getCodecCompatibleName(\n  codec: string,\n  preferManagedMediaSource = true,\n): string {\n  return codec.replace(AUDIO_CODEC_REGEXP, (m) =>\n    getCodecCompatibleNameLower(\n      m.toLowerCase() as LowerCaseCodecType,\n      preferManagedMediaSource,\n    ),\n  );\n}\n\nexport function pickMostCompleteCodecName(\n  parsedCodec: string,\n  levelCodec: string | undefined,\n): string | undefined {\n  // Parsing of mp4a codecs strings in mp4-tools from media is incomplete as of d8c6c7a\n  // so use level codec is parsed codec is unavailable or incomplete\n  if (parsedCodec && parsedCodec !== 'mp4a') {\n    return parsedCodec;\n  }\n  return levelCodec ? levelCodec.split(',')[0] : levelCodec;\n}\n\nexport function convertAVC1ToAVCOTI(codec: string) {\n  // Convert avc1 codec string from RFC-4281 to RFC-6381 for MediaSource.isTypeSupported\n  // Examples: avc1.66.30 to avc1.42001e and avc1.77.30,avc1.66.30 to avc1.4d001e,avc1.42001e.\n  const codecs = codec.split(',');\n  for (let i = 0; i < codecs.length; i++) {\n    const avcdata = codecs[i].split('.');\n    if (avcdata.length > 2) {\n      let result = avcdata.shift() + '.';\n      result += parseInt(avcdata.shift() as string).toString(16);\n      result += (\n        '000' + parseInt(avcdata.shift() as string).toString(16)\n      ).slice(-4);\n      codecs[i] = result;\n    }\n  }\n  return codecs.join(',');\n}\n", "import { buildAbsoluteURL } from 'url-toolkit';\nimport { DateRange } from './date-range';\nimport { Fragment, Part } from './fragment';\nimport { LevelDetails } from './level-details';\nimport { LevelKey } from './level-key';\nimport { AttrList } from '../utils/attr-list';\nimport { logger } from '../utils/logger';\nimport {\n  addVariableDefinition,\n  hasVariableReferences,\n  importVariableDefinition,\n  substituteVariables,\n  substituteVariablesInAttributes,\n} from '../utils/variable-substitution';\nimport { isCodecType } from '../utils/codecs';\nimport type { CodecType } from '../utils/codecs';\nimport type { MediaPlaylist, MediaAttributes } from '../types/media-playlist';\nimport type { PlaylistLevelType } from '../types/loader';\nimport type { LevelAttributes, LevelParsed, VariableMap } from '../types/level';\nimport type { ContentSteeringOptions } from '../types/events';\n\ntype M3U8ParserFragments = Array<Fragment | null>;\n\nexport type ParsedMultivariantPlaylist = {\n  contentSteering: ContentSteeringOptions | null;\n  levels: LevelParsed[];\n  playlistParsingError: Error | null;\n  sessionData: Record<string, AttrList> | null;\n  sessionKeys: LevelKey[] | null;\n  startTimeOffset: number | null;\n  variableList: VariableMap | null;\n  hasVariableRefs: boolean;\n};\n\ntype ParsedMultivariantMediaOptions = {\n  AUDIO?: MediaPlaylist[];\n  SUBTITLES?: MediaPlaylist[];\n  'CLOSED-CAPTIONS'?: MediaPlaylist[];\n};\n\nconst MASTER_PLAYLIST_REGEX =\n  /#EXT-X-STREAM-INF:([^\\r\\n]*)(?:[\\r\\n](?:#[^\\r\\n]*)?)*([^\\r\\n]+)|#EXT-X-(SESSION-DATA|SESSION-KEY|DEFINE|CONTENT-STEERING|START):([^\\r\\n]*)[\\r\\n]+/g;\nconst MASTER_PLAYLIST_MEDIA_REGEX = /#EXT-X-MEDIA:(.*)/g;\n\nconst IS_MEDIA_PLAYLIST = /^#EXT(?:INF|-X-TARGETDURATION):/m; // Handle empty Media Playlist (first EXTINF not signaled, but TARGETDURATION present)\n\nconst LEVEL_PLAYLIST_REGEX_FAST = new RegExp(\n  [\n    /#EXTINF:\\s*(\\d*(?:\\.\\d+)?)(?:,(.*)\\s+)?/.source, // duration (#EXTINF:<duration>,<title>), group 1 => duration, group 2 => title\n    /(?!#) *(\\S[^\\r\\n]*)/.source, // segment URI, group 3 => the URI (note newline is not eaten)\n    /#EXT-X-BYTERANGE:*(.+)/.source, // next segment's byterange, group 4 => range spec (x@y)\n    /#EXT-X-PROGRAM-DATE-TIME:(.+)/.source, // next segment's program date/time group 5 => the datetime spec\n    /#.*/.source, // All other non-segment oriented tags will match with all groups empty\n  ].join('|'),\n  'g',\n);\n\nconst LEVEL_PLAYLIST_REGEX_SLOW = new RegExp(\n  [\n    /#(EXTM3U)/.source,\n    /#EXT-X-(DATERANGE|DEFINE|KEY|MAP|PART|PART-INF|PLAYLIST-TYPE|PRELOAD-HINT|RENDITION-REPORT|SERVER-CONTROL|SKIP|START):(.+)/\n      .source,\n    /#EXT-X-(BITRATE|DISCONTINUITY-SEQUENCE|MEDIA-SEQUENCE|TARGETDURATION|VERSION): *(\\d+)/\n      .source,\n    /#EXT-X-(DISCONTINUITY|ENDLIST|GAP|INDEPENDENT-SEGMENTS)/.source,\n    /(#)([^:]*):(.*)/.source,\n    /(#)(.*)(?:.*)\\r?\\n?/.source,\n  ].join('|'),\n);\n\nexport default class M3U8Parser {\n  static findGroup(\n    groups: (\n      | { id?: string; audioCodec?: string }\n      | { id?: string; textCodec?: string }\n    )[],\n    mediaGroupId: string,\n  ):\n    | { id?: string; audioCodec?: string }\n    | { id?: string; textCodec?: string }\n    | undefined {\n    for (let i = 0; i < groups.length; i++) {\n      const group = groups[i];\n      if (group.id === mediaGroupId) {\n        return group;\n      }\n    }\n  }\n\n  static resolve(url, baseUrl) {\n    return buildAbsoluteURL(baseUrl, url, { alwaysNormalize: true });\n  }\n\n  static isMediaPlaylist(str: string): boolean {\n    return IS_MEDIA_PLAYLIST.test(str);\n  }\n\n  static parseMasterPlaylist(\n    string: string,\n    baseurl: string,\n  ): ParsedMultivariantPlaylist {\n    const hasVariableRefs = __USE_VARIABLE_SUBSTITUTION__\n      ? hasVariableReferences(string)\n      : false;\n    const parsed: ParsedMultivariantPlaylist = {\n      contentSteering: null,\n      levels: [],\n      playlistParsingError: null,\n      sessionData: null,\n      sessionKeys: null,\n      startTimeOffset: null,\n      variableList: null,\n      hasVariableRefs,\n    };\n    const levelsWithKnownCodecs: LevelParsed[] = [];\n\n    MASTER_PLAYLIST_REGEX.lastIndex = 0;\n\n    let result: RegExpExecArray | null;\n    while ((result = MASTER_PLAYLIST_REGEX.exec(string)) != null) {\n      if (result[1]) {\n        // '#EXT-X-STREAM-INF' is found, parse level tag  in group 1\n        const attrs = new AttrList(result[1]) as LevelAttributes;\n        if (__USE_VARIABLE_SUBSTITUTION__) {\n          substituteVariablesInAttributes(parsed, attrs, [\n            'CODECS',\n            'SUPPLEMENTAL-CODECS',\n            'ALLOWED-CPC',\n            'PATHWAY-ID',\n            'STABLE-VARIANT-ID',\n            'AUDIO',\n            'VIDEO',\n            'SUBTITLES',\n            'CLOSED-CAPTIONS',\n            'NAME',\n          ]);\n        }\n        const uri = __USE_VARIABLE_SUBSTITUTION__\n          ? substituteVariables(parsed, result[2])\n          : result[2];\n        const level: LevelParsed = {\n          attrs,\n          bitrate:\n            attrs.decimalInteger('BANDWIDTH') ||\n            attrs.decimalInteger('AVERAGE-BANDWIDTH'),\n          name: attrs.NAME,\n          url: M3U8Parser.resolve(uri, baseurl),\n        };\n\n        const resolution = attrs.decimalResolution('RESOLUTION');\n        if (resolution) {\n          level.width = resolution.width;\n          level.height = resolution.height;\n        }\n\n        setCodecs(attrs.CODECS, level);\n\n        if (!level.unknownCodecs?.length) {\n          levelsWithKnownCodecs.push(level);\n        }\n\n        parsed.levels.push(level);\n      } else if (result[3]) {\n        const tag = result[3];\n        const attributes = result[4];\n        switch (tag) {\n          case 'SESSION-DATA': {\n            // #EXT-X-SESSION-DATA\n            const sessionAttrs = new AttrList(attributes);\n            if (__USE_VARIABLE_SUBSTITUTION__) {\n              substituteVariablesInAttributes(parsed, sessionAttrs, [\n                'DATA-ID',\n                'LANGUAGE',\n                'VALUE',\n                'URI',\n              ]);\n            }\n            const dataId = sessionAttrs['DATA-ID'];\n            if (dataId) {\n              if (parsed.sessionData === null) {\n                parsed.sessionData = {};\n              }\n              parsed.sessionData[dataId] = sessionAttrs;\n            }\n            break;\n          }\n          case 'SESSION-KEY': {\n            // #EXT-X-SESSION-KEY\n            const sessionKey = parseKey(attributes, baseurl, parsed);\n            if (sessionKey.encrypted && sessionKey.isSupported()) {\n              if (parsed.sessionKeys === null) {\n                parsed.sessionKeys = [];\n              }\n              parsed.sessionKeys.push(sessionKey);\n            } else {\n              logger.warn(\n                `[Keys] Ignoring invalid EXT-X-SESSION-KEY tag: \"${attributes}\"`,\n              );\n            }\n            break;\n          }\n          case 'DEFINE': {\n            // #EXT-X-DEFINE\n            if (__USE_VARIABLE_SUBSTITUTION__) {\n              const variableAttributes = new AttrList(attributes);\n              substituteVariablesInAttributes(parsed, variableAttributes, [\n                'NAME',\n                'VALUE',\n                'QUERYPARAM',\n              ]);\n              addVariableDefinition(parsed, variableAttributes, baseurl);\n            }\n            break;\n          }\n          case 'CONTENT-STEERING': {\n            // #EXT-X-CONTENT-STEERING\n            const contentSteeringAttributes = new AttrList(attributes);\n            if (__USE_VARIABLE_SUBSTITUTION__) {\n              substituteVariablesInAttributes(\n                parsed,\n                contentSteeringAttributes,\n                ['SERVER-URI', 'PATHWAY-ID'],\n              );\n            }\n            parsed.contentSteering = {\n              uri: M3U8Parser.resolve(\n                contentSteeringAttributes['SERVER-URI'],\n                baseurl,\n              ),\n              pathwayId: contentSteeringAttributes['PATHWAY-ID'] || '.',\n            };\n            break;\n          }\n          case 'START': {\n            // #EXT-X-START\n            parsed.startTimeOffset = parseStartTimeOffset(attributes);\n            break;\n          }\n          default:\n            break;\n        }\n      }\n    }\n    // Filter out levels with unknown codecs if it does not remove all levels\n    const stripUnknownCodecLevels =\n      levelsWithKnownCodecs.length > 0 &&\n      levelsWithKnownCodecs.length < parsed.levels.length;\n\n    parsed.levels = stripUnknownCodecLevels\n      ? levelsWithKnownCodecs\n      : parsed.levels;\n    if (parsed.levels.length === 0) {\n      parsed.playlistParsingError = new Error('no levels found in manifest');\n    }\n\n    return parsed;\n  }\n\n  static parseMasterPlaylistMedia(\n    string: string,\n    baseurl: string,\n    parsed: ParsedMultivariantPlaylist,\n  ): ParsedMultivariantMediaOptions {\n    let result: RegExpExecArray | null;\n    const results: ParsedMultivariantMediaOptions = {};\n    const levels = parsed.levels;\n    const groupsByType = {\n      AUDIO: levels.map((level: LevelParsed) => ({\n        id: level.attrs.AUDIO,\n        audioCodec: level.audioCodec,\n      })),\n      SUBTITLES: levels.map((level: LevelParsed) => ({\n        id: level.attrs.SUBTITLES,\n        textCodec: level.textCodec,\n      })),\n      'CLOSED-CAPTIONS': [],\n    };\n    let id = 0;\n    MASTER_PLAYLIST_MEDIA_REGEX.lastIndex = 0;\n    while ((result = MASTER_PLAYLIST_MEDIA_REGEX.exec(string)) !== null) {\n      const attrs = new AttrList(result[1]) as MediaAttributes;\n      const type = attrs.TYPE;\n      if (type) {\n        const groups: (typeof groupsByType)[keyof typeof groupsByType] =\n          groupsByType[type];\n        const medias: MediaPlaylist[] = results[type] || [];\n        results[type] = medias;\n        if (__USE_VARIABLE_SUBSTITUTION__) {\n          substituteVariablesInAttributes(parsed, attrs, [\n            'URI',\n            'GROUP-ID',\n            'LANGUAGE',\n            'ASSOC-LANGUAGE',\n            'STABLE-RENDITION-ID',\n            'NAME',\n            'INSTREAM-ID',\n            'CHARACTERISTICS',\n            'CHANNELS',\n          ]);\n        }\n        const lang = attrs.LANGUAGE;\n        const assocLang = attrs['ASSOC-LANGUAGE'];\n        const channels = attrs.CHANNELS;\n        const characteristics = attrs.CHARACTERISTICS;\n        const instreamId = attrs['INSTREAM-ID'];\n        const media: MediaPlaylist = {\n          attrs,\n          bitrate: 0,\n          id: id++,\n          groupId: attrs['GROUP-ID'] || '',\n          name: attrs.NAME || lang || '',\n          type,\n          default: attrs.bool('DEFAULT'),\n          autoselect: attrs.bool('AUTOSELECT'),\n          forced: attrs.bool('FORCED'),\n          lang,\n          url: attrs.URI ? M3U8Parser.resolve(attrs.URI, baseurl) : '',\n        };\n        if (assocLang) {\n          media.assocLang = assocLang;\n        }\n        if (channels) {\n          media.channels = channels;\n        }\n        if (characteristics) {\n          media.characteristics = characteristics;\n        }\n        if (instreamId) {\n          media.instreamId = instreamId;\n        }\n\n        if (groups?.length) {\n          // If there are audio or text groups signalled in the manifest, let's look for a matching codec string for this track\n          // If we don't find the track signalled, lets use the first audio groups codec we have\n          // Acting as a best guess\n          const groupCodec =\n            M3U8Parser.findGroup(groups, media.groupId as string) || groups[0];\n          assignCodec(media, groupCodec, 'audioCodec');\n          assignCodec(media, groupCodec, 'textCodec');\n        }\n\n        medias.push(media);\n      }\n    }\n    return results;\n  }\n\n  static parseLevelPlaylist(\n    string: string,\n    baseurl: string,\n    id: number,\n    type: PlaylistLevelType,\n    levelUrlId: number,\n    multivariantVariableList: VariableMap | null,\n  ): LevelDetails {\n    const level = new LevelDetails(baseurl);\n    const fragments: M3U8ParserFragments = level.fragments;\n    // The most recent init segment seen (applies to all subsequent segments)\n    let currentInitSegment: Fragment | null = null;\n    let currentSN = 0;\n    let currentPart = 0;\n    let totalduration = 0;\n    let discontinuityCounter = 0;\n    let prevFrag: Fragment | null = null;\n    let frag: Fragment = new Fragment(type, baseurl);\n    let result: RegExpExecArray | RegExpMatchArray | null;\n    let i: number;\n    let levelkeys: { [key: string]: LevelKey } | undefined;\n    let firstPdtIndex = -1;\n    let createNextFrag = false;\n    let nextByteRange: string | null = null;\n\n    LEVEL_PLAYLIST_REGEX_FAST.lastIndex = 0;\n    level.m3u8 = string;\n    level.hasVariableRefs = __USE_VARIABLE_SUBSTITUTION__\n      ? hasVariableReferences(string)\n      : false;\n\n    while ((result = LEVEL_PLAYLIST_REGEX_FAST.exec(string)) !== null) {\n      if (createNextFrag) {\n        createNextFrag = false;\n        frag = new Fragment(type, baseurl);\n        // setup the next fragment for part loading\n        frag.start = totalduration;\n        frag.sn = currentSN;\n        frag.cc = discontinuityCounter;\n        frag.level = id;\n        if (currentInitSegment) {\n          frag.initSegment = currentInitSegment;\n          frag.rawProgramDateTime = currentInitSegment.rawProgramDateTime;\n          currentInitSegment.rawProgramDateTime = null;\n          if (nextByteRange) {\n            frag.setByteRange(nextByteRange);\n            nextByteRange = null;\n          }\n        }\n      }\n\n      const duration = result[1];\n      if (duration) {\n        // INF\n        frag.duration = parseFloat(duration);\n        // avoid sliced strings    https://github.com/video-dev/hls.js/issues/939\n        const title = (' ' + result[2]).slice(1);\n        frag.title = title || null;\n        frag.tagList.push(title ? ['INF', duration, title] : ['INF', duration]);\n      } else if (result[3]) {\n        // url\n        if (Number.isFinite(frag.duration)) {\n          frag.start = totalduration;\n          if (levelkeys) {\n            setFragLevelKeys(frag, levelkeys, level);\n          }\n          frag.sn = currentSN;\n          frag.level = id;\n          frag.cc = discontinuityCounter;\n          fragments.push(frag);\n          // avoid sliced strings    https://github.com/video-dev/hls.js/issues/939\n          const uri = (' ' + result[3]).slice(1);\n          frag.relurl = __USE_VARIABLE_SUBSTITUTION__\n            ? substituteVariables(level, uri)\n            : uri;\n          assignProgramDateTime(frag, prevFrag);\n          prevFrag = frag;\n          totalduration += frag.duration;\n          currentSN++;\n          currentPart = 0;\n          createNextFrag = true;\n        }\n      } else if (result[4]) {\n        // X-BYTERANGE\n        const data = (' ' + result[4]).slice(1);\n        if (prevFrag) {\n          frag.setByteRange(data, prevFrag);\n        } else {\n          frag.setByteRange(data);\n        }\n      } else if (result[5]) {\n        // PROGRAM-DATE-TIME\n        // avoid sliced strings    https://github.com/video-dev/hls.js/issues/939\n        frag.rawProgramDateTime = (' ' + result[5]).slice(1);\n        frag.tagList.push(['PROGRAM-DATE-TIME', frag.rawProgramDateTime]);\n        if (firstPdtIndex === -1) {\n          firstPdtIndex = fragments.length;\n        }\n      } else {\n        result = result[0].match(LEVEL_PLAYLIST_REGEX_SLOW);\n        if (!result) {\n          logger.warn('No matches on slow regex match for level playlist!');\n          continue;\n        }\n        for (i = 1; i < result.length; i++) {\n          if (typeof result[i] !== 'undefined') {\n            break;\n          }\n        }\n\n        // avoid sliced strings    https://github.com/video-dev/hls.js/issues/939\n        const tag = (' ' + result[i]).slice(1);\n        const value1 = (' ' + result[i + 1]).slice(1);\n        const value2 = result[i + 2] ? (' ' + result[i + 2]).slice(1) : '';\n\n        switch (tag) {\n          case 'PLAYLIST-TYPE':\n            level.type = value1.toUpperCase();\n            break;\n          case 'MEDIA-SEQUENCE':\n            currentSN = level.startSN = parseInt(value1);\n            break;\n          case 'SKIP': {\n            const skipAttrs = new AttrList(value1);\n            if (__USE_VARIABLE_SUBSTITUTION__) {\n              substituteVariablesInAttributes(level, skipAttrs, [\n                'RECENTLY-REMOVED-DATERANGES',\n              ]);\n            }\n            const skippedSegments =\n              skipAttrs.decimalInteger('SKIPPED-SEGMENTS');\n            if (Number.isFinite(skippedSegments)) {\n              level.skippedSegments = skippedSegments;\n              // This will result in fragments[] containing undefined values, which we will fill in with `mergeDetails`\n              for (let i = skippedSegments; i--; ) {\n                fragments.unshift(null);\n              }\n              currentSN += skippedSegments;\n            }\n            const recentlyRemovedDateranges = skipAttrs.enumeratedString(\n              'RECENTLY-REMOVED-DATERANGES',\n            );\n            if (recentlyRemovedDateranges) {\n              level.recentlyRemovedDateranges =\n                recentlyRemovedDateranges.split('\\t');\n            }\n            break;\n          }\n          case 'TARGETDURATION':\n            level.targetduration = Math.max(parseInt(value1), 1);\n            break;\n          case 'VERSION':\n            level.version = parseInt(value1);\n            break;\n          case 'INDEPENDENT-SEGMENTS':\n          case 'EXTM3U':\n            break;\n          case 'ENDLIST':\n            level.live = false;\n            break;\n          case '#':\n            if (value1 || value2) {\n              frag.tagList.push(value2 ? [value1, value2] : [value1]);\n            }\n            break;\n          case 'DISCONTINUITY':\n            discontinuityCounter++;\n            frag.tagList.push(['DIS']);\n            break;\n          case 'GAP':\n            frag.gap = true;\n            frag.tagList.push([tag]);\n            break;\n          case 'BITRATE':\n            frag.tagList.push([tag, value1]);\n            break;\n          case 'DATERANGE': {\n            const dateRangeAttr = new AttrList(value1);\n            if (__USE_VARIABLE_SUBSTITUTION__) {\n              substituteVariablesInAttributes(level, dateRangeAttr, [\n                'ID',\n                'CLASS',\n                'START-DATE',\n                'END-DATE',\n                'SCTE35-CMD',\n                'SCTE35-OUT',\n                'SCTE35-IN',\n              ]);\n              substituteVariablesInAttributes(\n                level,\n                dateRangeAttr,\n                dateRangeAttr.clientAttrs,\n              );\n            }\n            const dateRange = new DateRange(\n              dateRangeAttr,\n              level.dateRanges[dateRangeAttr.ID],\n            );\n            if (dateRange.isValid || level.skippedSegments) {\n              level.dateRanges[dateRange.id] = dateRange;\n            } else {\n              logger.warn(`Ignoring invalid DATERANGE tag: \"${value1}\"`);\n            }\n            // Add to fragment tag list for backwards compatibility (< v1.2.0)\n            frag.tagList.push(['EXT-X-DATERANGE', value1]);\n            break;\n          }\n          case 'DEFINE': {\n            if (__USE_VARIABLE_SUBSTITUTION__) {\n              const variableAttributes = new AttrList(value1);\n              substituteVariablesInAttributes(level, variableAttributes, [\n                'NAME',\n                'VALUE',\n                'IMPORT',\n                'QUERYPARAM',\n              ]);\n              if ('IMPORT' in variableAttributes) {\n                importVariableDefinition(\n                  level,\n                  variableAttributes,\n                  multivariantVariableList,\n                );\n              } else {\n                addVariableDefinition(level, variableAttributes, baseurl);\n              }\n            }\n            break;\n          }\n\n          case 'DISCONTINUITY-SEQUENCE':\n            discontinuityCounter = parseInt(value1);\n            break;\n          case 'KEY': {\n            const levelKey = parseKey(value1, baseurl, level);\n            if (levelKey.isSupported()) {\n              if (levelKey.method === 'NONE') {\n                levelkeys = undefined;\n                break;\n              }\n              if (!levelkeys) {\n                levelkeys = {};\n              }\n              if (levelkeys[levelKey.keyFormat]) {\n                levelkeys = Object.assign({}, levelkeys);\n              }\n              levelkeys[levelKey.keyFormat] = levelKey;\n            } else {\n              logger.warn(`[Keys] Ignoring invalid EXT-X-KEY tag: \"${value1}\"`);\n            }\n            break;\n          }\n          case 'START':\n            level.startTimeOffset = parseStartTimeOffset(value1);\n            break;\n          case 'MAP': {\n            const mapAttrs = new AttrList(value1);\n            if (__USE_VARIABLE_SUBSTITUTION__) {\n              substituteVariablesInAttributes(level, mapAttrs, [\n                'BYTERANGE',\n                'URI',\n              ]);\n            }\n            if (frag.duration) {\n              // Initial segment tag is after segment duration tag.\n              //   #EXTINF: 6.0\n              //   #EXT-X-MAP:URI=\"init.mp4\n              const init = new Fragment(type, baseurl);\n              setInitSegment(init, mapAttrs, id, levelkeys);\n              currentInitSegment = init;\n              frag.initSegment = currentInitSegment;\n              if (\n                currentInitSegment.rawProgramDateTime &&\n                !frag.rawProgramDateTime\n              ) {\n                frag.rawProgramDateTime = currentInitSegment.rawProgramDateTime;\n              }\n            } else {\n              // Initial segment tag is before segment duration tag\n              // Handle case where EXT-X-MAP is declared after EXT-X-BYTERANGE\n              const end = frag.byteRangeEndOffset;\n              if (end) {\n                const start = frag.byteRangeStartOffset as number;\n                nextByteRange = `${end - start}@${start}`;\n              } else {\n                nextByteRange = null;\n              }\n              setInitSegment(frag, mapAttrs, id, levelkeys);\n              currentInitSegment = frag;\n              createNextFrag = true;\n            }\n            break;\n          }\n          case 'SERVER-CONTROL': {\n            const serverControlAttrs = new AttrList(value1);\n            level.canBlockReload = serverControlAttrs.bool('CAN-BLOCK-RELOAD');\n            level.canSkipUntil = serverControlAttrs.optionalFloat(\n              'CAN-SKIP-UNTIL',\n              0,\n            );\n            level.canSkipDateRanges =\n              level.canSkipUntil > 0 &&\n              serverControlAttrs.bool('CAN-SKIP-DATERANGES');\n            level.partHoldBack = serverControlAttrs.optionalFloat(\n              'PART-HOLD-BACK',\n              0,\n            );\n            level.holdBack = serverControlAttrs.optionalFloat('HOLD-BACK', 0);\n            break;\n          }\n          case 'PART-INF': {\n            const partInfAttrs = new AttrList(value1);\n            level.partTarget = partInfAttrs.decimalFloatingPoint('PART-TARGET');\n            break;\n          }\n          case 'PART': {\n            let partList = level.partList;\n            if (!partList) {\n              partList = level.partList = [];\n            }\n            const previousFragmentPart =\n              currentPart > 0 ? partList[partList.length - 1] : undefined;\n            const index = currentPart++;\n            const partAttrs = new AttrList(value1);\n            if (__USE_VARIABLE_SUBSTITUTION__) {\n              substituteVariablesInAttributes(level, partAttrs, [\n                'BYTERANGE',\n                'URI',\n              ]);\n            }\n            const part = new Part(\n              partAttrs,\n              frag,\n              baseurl,\n              index,\n              previousFragmentPart,\n            );\n            partList.push(part);\n            frag.duration += part.duration;\n            break;\n          }\n          case 'PRELOAD-HINT': {\n            const preloadHintAttrs = new AttrList(value1);\n            if (__USE_VARIABLE_SUBSTITUTION__) {\n              substituteVariablesInAttributes(level, preloadHintAttrs, ['URI']);\n            }\n            level.preloadHint = preloadHintAttrs;\n            break;\n          }\n          case 'RENDITION-REPORT': {\n            const renditionReportAttrs = new AttrList(value1);\n            if (__USE_VARIABLE_SUBSTITUTION__) {\n              substituteVariablesInAttributes(level, renditionReportAttrs, [\n                'URI',\n              ]);\n            }\n            level.renditionReports = level.renditionReports || [];\n            level.renditionReports.push(renditionReportAttrs);\n            break;\n          }\n          default:\n            logger.warn(`line parsed but not handled: ${result}`);\n            break;\n        }\n      }\n    }\n    if (prevFrag && !prevFrag.relurl) {\n      fragments.pop();\n      totalduration -= prevFrag.duration;\n      if (level.partList) {\n        level.fragmentHint = prevFrag;\n      }\n    } else if (level.partList) {\n      assignProgramDateTime(frag, prevFrag);\n      frag.cc = discontinuityCounter;\n      level.fragmentHint = frag;\n      if (levelkeys) {\n        setFragLevelKeys(frag, levelkeys, level);\n      }\n    }\n    const fragmentLength = fragments.length;\n    const firstFragment = fragments[0];\n    const lastFragment = fragments[fragmentLength - 1];\n    totalduration += level.skippedSegments * level.targetduration;\n    if (totalduration > 0 && fragmentLength && lastFragment) {\n      level.averagetargetduration = totalduration / fragmentLength;\n      const lastSn = lastFragment.sn;\n      level.endSN = lastSn !== 'initSegment' ? lastSn : 0;\n      if (!level.live) {\n        lastFragment.endList = true;\n      }\n      if (firstFragment) {\n        level.startCC = firstFragment.cc;\n      }\n    } else {\n      level.endSN = 0;\n      level.startCC = 0;\n    }\n    if (level.fragmentHint) {\n      totalduration += level.fragmentHint.duration;\n    }\n    level.totalduration = totalduration;\n    level.endCC = discontinuityCounter;\n\n    /**\n     * Backfill any missing PDT values\n     * \"If the first EXT-X-PROGRAM-DATE-TIME tag in a Playlist appears after\n     * one or more Media Segment URIs, the client SHOULD extrapolate\n     * backward from that tag (using EXTINF durations and/or media\n     * timestamps) to associate dates with those segments.\"\n     * We have already extrapolated forward, but all fragments up to the first instance of PDT do not have their PDTs\n     * computed.\n     */\n    if (firstPdtIndex > 0) {\n      backfillProgramDateTimes(fragments, firstPdtIndex);\n    }\n\n    return level;\n  }\n}\n\nfunction parseKey(\n  keyTagAttributes: string,\n  baseurl: string,\n  parsed: ParsedMultivariantPlaylist | LevelDetails,\n): LevelKey {\n  // https://tools.ietf.org/html/rfc8216#section-4.3.2.4\n  const keyAttrs = new AttrList(keyTagAttributes);\n  if (__USE_VARIABLE_SUBSTITUTION__) {\n    substituteVariablesInAttributes(parsed, keyAttrs, [\n      'KEYFORMAT',\n      'KEYFORMATVERSIONS',\n      'URI',\n      'IV',\n      'URI',\n    ]);\n  }\n  const decryptmethod = keyAttrs.METHOD ?? '';\n  const decrypturi = keyAttrs.URI;\n  const decryptiv = keyAttrs.hexadecimalInteger('IV');\n  const decryptkeyformatversions = keyAttrs.KEYFORMATVERSIONS;\n  // From RFC: This attribute is OPTIONAL; its absence indicates an implicit value of \"identity\".\n  const decryptkeyformat = keyAttrs.KEYFORMAT ?? 'identity';\n\n  if (decrypturi && keyAttrs.IV && !decryptiv) {\n    logger.error(`Invalid IV: ${keyAttrs.IV}`);\n  }\n  // If decrypturi is a URI with a scheme, then baseurl will be ignored\n  // No uri is allowed when METHOD is NONE\n  const resolvedUri = decrypturi ? M3U8Parser.resolve(decrypturi, baseurl) : '';\n  const keyFormatVersions = (\n    decryptkeyformatversions ? decryptkeyformatversions : '1'\n  )\n    .split('/')\n    .map(Number)\n    .filter(Number.isFinite);\n\n  return new LevelKey(\n    decryptmethod,\n    resolvedUri,\n    decryptkeyformat,\n    keyFormatVersions,\n    decryptiv,\n  );\n}\n\nfunction parseStartTimeOffset(startAttributes: string): number | null {\n  const startAttrs = new AttrList(startAttributes);\n  const startTimeOffset = startAttrs.decimalFloatingPoint('TIME-OFFSET');\n  if (Number.isFinite(startTimeOffset)) {\n    return startTimeOffset;\n  }\n  return null;\n}\n\nfunction setCodecs(\n  codecsAttributeValue: string | undefined,\n  level: LevelParsed,\n) {\n  let codecs = (codecsAttributeValue || '').split(/[ ,]+/).filter((c) => c);\n  ['video', 'audio', 'text'].forEach((type: CodecType) => {\n    const filtered = codecs.filter((codec) => isCodecType(codec, type));\n    if (filtered.length) {\n      // Comma separated list of all codecs for type\n      level[`${type}Codec`] = filtered.join(',');\n      // Remove known codecs so that only unknownCodecs are left after iterating through each type\n      codecs = codecs.filter((codec) => filtered.indexOf(codec) === -1);\n    }\n  });\n  level.unknownCodecs = codecs;\n}\n\nfunction assignCodec(\n  media: MediaPlaylist,\n  groupItem: { audioCodec?: string; textCodec?: string },\n  codecProperty: 'audioCodec' | 'textCodec',\n) {\n  const codecValue = groupItem[codecProperty];\n  if (codecValue) {\n    media[codecProperty] = codecValue;\n  }\n}\n\nfunction backfillProgramDateTimes(\n  fragments: M3U8ParserFragments,\n  firstPdtIndex: number,\n) {\n  let fragPrev = fragments[firstPdtIndex] as Fragment;\n  for (let i = firstPdtIndex; i--; ) {\n    const frag = fragments[i];\n    // Exit on delta-playlist skipped segments\n    if (!frag) {\n      return;\n    }\n    frag.programDateTime =\n      (fragPrev.programDateTime as number) - frag.duration * 1000;\n    fragPrev = frag;\n  }\n}\n\nfunction assignProgramDateTime(frag, prevFrag) {\n  if (frag.rawProgramDateTime) {\n    frag.programDateTime = Date.parse(frag.rawProgramDateTime);\n  } else if (prevFrag?.programDateTime) {\n    frag.programDateTime = prevFrag.endProgramDateTime;\n  }\n\n  if (!Number.isFinite(frag.programDateTime)) {\n    frag.programDateTime = null;\n    frag.rawProgramDateTime = null;\n  }\n}\n\nfunction setInitSegment(\n  frag: Fragment,\n  mapAttrs: AttrList,\n  id: number,\n  levelkeys: { [key: string]: LevelKey } | undefined,\n) {\n  frag.relurl = mapAttrs.URI;\n  if (mapAttrs.BYTERANGE) {\n    frag.setByteRange(mapAttrs.BYTERANGE);\n  }\n  frag.level = id;\n  frag.sn = 'initSegment';\n  if (levelkeys) {\n    frag.levelkeys = levelkeys;\n  }\n  frag.initSegment = null;\n}\n\nfunction setFragLevelKeys(\n  frag: Fragment,\n  levelkeys: { [key: string]: LevelKey },\n  level: LevelDetails,\n) {\n  frag.levelkeys = levelkeys;\n  const { encryptedFragments } = level;\n  if (\n    (!encryptedFragments.length ||\n      encryptedFragments[encryptedFragments.length - 1].levelkeys !==\n        levelkeys) &&\n    Object.keys(levelkeys).some(\n      (format) => levelkeys![format].isCommonEncryption,\n    )\n  ) {\n    encryptedFragments.push(frag);\n  }\n}\n", "import type { LoaderConfig } from '../config';\nimport type { Fragment } from '../loader/fragment';\nimport type { Part } from '../loader/fragment';\nimport type { KeyLoaderInfo } from '../loader/key-loader';\nimport type { LevelDetails } from '../loader/level-details';\nimport type { HlsUrlParameters } from './level';\n\nexport interface LoaderContext {\n  // target URL\n  url: string;\n  // loader response type (arraybuffer or default response type for playlist)\n  responseType: string;\n  // headers\n  headers?: Record<string, string>;\n  // start byte range offset\n  rangeStart?: number;\n  // end byte range offset\n  rangeEnd?: number;\n  // true if onProgress should report partial chunk of loaded content\n  progressData?: boolean;\n}\n\nexport interface FragmentLoaderContext extends LoaderContext {\n  frag: Fragment;\n  part: Part | null;\n  resetIV?: boolean;\n}\n\nexport interface KeyLoaderContext extends LoaderContext {\n  keyInfo: KeyLoaderInfo;\n  frag: Fragment;\n}\n\nexport interface LoaderConfiguration {\n  // LoaderConfig policy that overrides required settings\n  loadPolicy: LoaderConfig;\n  /**\n   * @deprecated use LoaderConfig timeoutRetry and errorRetry maxNumRetry\n   */\n  // Max number of load retries\n  maxRetry: number;\n  /**\n   * @deprecated use LoaderConfig maxTimeToFirstByteMs and maxLoadTimeMs\n   */\n  // Timeout after which `onTimeOut` callback will be triggered\n  //  when loading has not finished after that delay\n  timeout: number;\n  /**\n   * @deprecated use LoaderConfig timeoutRetry and errorRetry retryDelayMs\n   */\n  // Delay between an I/O error and following connection retry (ms).\n  // This to avoid spamming the server\n  retryDelay: number;\n  /**\n   * @deprecated use LoaderConfig timeoutRetry and errorRetry maxRetryDelayMs\n   */\n  // max connection retry delay (ms)\n  maxRetryDelay: number;\n  // When streaming progressively, this is the minimum chunk size required to emit a PROGRESS event\n  highWaterMark?: number;\n}\n\nexport interface LoaderResponse {\n  url: string;\n  data?: string | ArrayBuffer | Object;\n  // Errors can include HTTP status code and error message\n  // Successful responses should include status code 200\n  code?: number;\n  text?: string;\n}\n\nexport interface LoaderStats {\n  aborted: boolean;\n  loaded: number;\n  retry: number;\n  total: number;\n  chunkCount: number;\n  bwEstimate: number;\n  loading: HlsProgressivePerformanceTiming;\n  parsing: HlsPerformanceTiming;\n  buffering: HlsProgressivePerformanceTiming;\n}\n\nexport interface HlsPerformanceTiming {\n  start: number;\n  end: number;\n}\n\nexport interface HlsChunkPerformanceTiming extends HlsPerformanceTiming {\n  executeStart: number;\n  executeEnd: number;\n}\n\nexport interface HlsProgressivePerformanceTiming extends HlsPerformanceTiming {\n  first: number;\n}\n\nexport type LoaderOnSuccess<T extends LoaderContext> = (\n  response: LoaderResponse,\n  stats: LoaderStats,\n  context: T,\n  networkDetails: any,\n) => void;\n\nexport type LoaderOnProgress<T extends LoaderContext> = (\n  stats: LoaderStats,\n  context: T,\n  data: string | ArrayBuffer,\n  networkDetails: any,\n) => void;\n\nexport type LoaderOnError<T extends LoaderContext> = (\n  error: {\n    // error status code\n    code: number;\n    // error description\n    text: string;\n  },\n  context: T,\n  networkDetails: any,\n  stats: LoaderStats,\n) => void;\n\nexport type LoaderOnTimeout<T extends LoaderContext> = (\n  stats: LoaderStats,\n  context: T,\n  networkDetails: any,\n) => void;\n\nexport type LoaderOnAbort<T extends LoaderContext> = (\n  stats: LoaderStats,\n  context: T,\n  networkDetails: any,\n) => void;\n\nexport interface LoaderCallbacks<T extends LoaderContext> {\n  onSuccess: LoaderOnSuccess<T>;\n  onError: LoaderOnError<T>;\n  onTimeout: LoaderOnTimeout<T>;\n  onAbort?: LoaderOnAbort<T>;\n  onProgress?: LoaderOnProgress<T>;\n}\n\nexport interface Loader<T extends LoaderContext> {\n  destroy(): void;\n  abort(): void;\n  load(\n    context: T,\n    config: LoaderConfiguration,\n    callbacks: LoaderCallbacks<T>,\n  ): void;\n  /**\n   * `getCacheAge()` is called by hls.js to get the duration that a given object\n   * has been sitting in a cache proxy when playing live.  If implemented,\n   * this should return a value in seconds.\n   *\n   * For HTTP based loaders, this should return the contents of the \"age\" header.\n   *\n   * @returns time object being lodaded\n   */\n  getCacheAge?: () => number | null;\n  getResponseHeader?: (name: string) => string | null;\n  context: T | null;\n  stats: LoaderStats;\n}\n\nexport const enum PlaylistContextType {\n  MANIFEST = 'manifest',\n  LEVEL = 'level',\n  AUDIO_TRACK = 'audioTrack',\n  SUBTITLE_TRACK = 'subtitleTrack',\n}\n\nexport const enum PlaylistLevelType {\n  MAIN = 'main',\n  AUDIO = 'audio',\n  SUBTITLE = 'subtitle',\n}\n\nexport interface PlaylistLoaderContext extends LoaderContext {\n  type: PlaylistContextType;\n  // the level index to load\n  level: number | null;\n  // level or track id from LevelLoadingData / TrackLoadingData\n  id: number | null;\n  // Media Playlist Group ID\n  groupId?: string;\n  // Content Steering Pathway ID (or undefined for default Pathway \".\")\n  pathwayId?: string;\n  // internal representation of a parsed m3u8 level playlist\n  levelDetails?: LevelDetails;\n  // Blocking playlist request delivery directives (or null id none were added to playlist url\n  deliveryDirectives: HlsUrlParameters | null;\n}\n", "/**\n * PlaylistLoader - delegate for media manifest/playlist loading tasks. Takes care of parsing media to internal data-models.\n *\n * Once loaded, dispatches events with parsed data-models of manifest/levels/audio/subtitle tracks.\n *\n * Uses loader(s) set in config to do actual internal loading of resource tasks.\n */\n\nimport { Events } from '../events';\nimport { ErrorDetails, ErrorTypes } from '../errors';\nimport { logger } from '../utils/logger';\nimport M3U8Parser from './m3u8-parser';\nimport type { LevelParsed, VariableMap } from '../types/level';\nimport type {\n  Loader,\n  LoaderCallbacks,\n  LoaderConfiguration,\n  LoaderContext,\n  LoaderResponse,\n  LoaderStats,\n  PlaylistLoaderContext,\n} from '../types/loader';\nimport { PlaylistContextType, PlaylistLevelType } from '../types/loader';\nimport { LevelDetails } from './level-details';\nimport { AttrList } from '../utils/attr-list';\nimport type Hls from '../hls';\nimport type {\n  ErrorData,\n  LevelLoadingData,\n  ManifestLoadingData,\n  TrackLoadingData,\n} from '../types/events';\nimport type { NetworkComponentAPI } from '../types/component-api';\nimport type { MediaAttributes } from '../types/media-playlist';\nimport type { LoaderConfig, RetryConfig } from '../config';\n\nfunction mapContextToLevelType(\n  context: PlaylistLoaderContext,\n): PlaylistLevelType {\n  const { type } = context;\n\n  switch (type) {\n    case PlaylistContextType.AUDIO_TRACK:\n      return PlaylistLevelType.AUDIO;\n    case PlaylistContextType.SUBTITLE_TRACK:\n      return PlaylistLevelType.SUBTITLE;\n    default:\n      return PlaylistLevelType.MAIN;\n  }\n}\n\nfunction getResponseUrl(\n  response: LoaderResponse,\n  context: PlaylistLoaderContext,\n): string {\n  let url = response.url;\n  // responseURL not supported on some browsers (it is used to detect URL redirection)\n  // data-uri mode also not supported (but no need to detect redirection)\n  if (url === undefined || url.indexOf('data:') === 0) {\n    // fallback to initial URL\n    url = context.url;\n  }\n  return url;\n}\n\nclass PlaylistLoader implements NetworkComponentAPI {\n  private readonly hls: Hls;\n  private readonly loaders: {\n    [key: string]: Loader<LoaderContext>;\n  } = Object.create(null);\n  private variableList: VariableMap | null = null;\n\n  constructor(hls: Hls) {\n    this.hls = hls;\n    this.registerListeners();\n  }\n\n  public startLoad(startPosition: number): void {}\n\n  public stopLoad(): void {\n    this.destroyInternalLoaders();\n  }\n\n  private registerListeners() {\n    const { hls } = this;\n    hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    hls.on(Events.LEVEL_LOADING, this.onLevelLoading, this);\n    hls.on(Events.AUDIO_TRACK_LOADING, this.onAudioTrackLoading, this);\n    hls.on(Events.SUBTITLE_TRACK_LOADING, this.onSubtitleTrackLoading, this);\n  }\n\n  private unregisterListeners() {\n    const { hls } = this;\n    hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    hls.off(Events.LEVEL_LOADING, this.onLevelLoading, this);\n    hls.off(Events.AUDIO_TRACK_LOADING, this.onAudioTrackLoading, this);\n    hls.off(Events.SUBTITLE_TRACK_LOADING, this.onSubtitleTrackLoading, this);\n  }\n\n  /**\n   * Returns defaults or configured loader-type overloads (pLoader and loader config params)\n   */\n  private createInternalLoader(\n    context: PlaylistLoaderContext,\n  ): Loader<LoaderContext> {\n    const config = this.hls.config;\n    const PLoader = config.pLoader;\n    const Loader = config.loader;\n    const InternalLoader = PLoader || Loader;\n    const loader = new InternalLoader(config) as Loader<PlaylistLoaderContext>;\n\n    this.loaders[context.type] = loader;\n    return loader;\n  }\n\n  private getInternalLoader(\n    context: PlaylistLoaderContext,\n  ): Loader<LoaderContext> | undefined {\n    return this.loaders[context.type];\n  }\n\n  private resetInternalLoader(contextType): void {\n    if (this.loaders[contextType]) {\n      delete this.loaders[contextType];\n    }\n  }\n\n  /**\n   * Call `destroy` on all internal loader instances mapped (one per context type)\n   */\n  private destroyInternalLoaders(): void {\n    for (const contextType in this.loaders) {\n      const loader = this.loaders[contextType];\n      if (loader) {\n        loader.destroy();\n      }\n\n      this.resetInternalLoader(contextType);\n    }\n  }\n\n  public destroy(): void {\n    this.variableList = null;\n    this.unregisterListeners();\n    this.destroyInternalLoaders();\n  }\n\n  private onManifestLoading(\n    event: Events.MANIFEST_LOADING,\n    data: ManifestLoadingData,\n  ) {\n    const { url } = data;\n    this.variableList = null;\n    this.load({\n      id: null,\n      level: 0,\n      responseType: 'text',\n      type: PlaylistContextType.MANIFEST,\n      url,\n      deliveryDirectives: null,\n    });\n  }\n\n  private onLevelLoading(event: Events.LEVEL_LOADING, data: LevelLoadingData) {\n    const { id, level, pathwayId, url, deliveryDirectives } = data;\n    this.load({\n      id,\n      level,\n      pathwayId,\n      responseType: 'text',\n      type: PlaylistContextType.LEVEL,\n      url,\n      deliveryDirectives,\n    });\n  }\n\n  private onAudioTrackLoading(\n    event: Events.AUDIO_TRACK_LOADING,\n    data: TrackLoadingData,\n  ) {\n    const { id, groupId, url, deliveryDirectives } = data;\n    this.load({\n      id,\n      groupId,\n      level: null,\n      responseType: 'text',\n      type: PlaylistContextType.AUDIO_TRACK,\n      url,\n      deliveryDirectives,\n    });\n  }\n\n  private onSubtitleTrackLoading(\n    event: Events.SUBTITLE_TRACK_LOADING,\n    data: TrackLoadingData,\n  ) {\n    const { id, groupId, url, deliveryDirectives } = data;\n    this.load({\n      id,\n      groupId,\n      level: null,\n      responseType: 'text',\n      type: PlaylistContextType.SUBTITLE_TRACK,\n      url,\n      deliveryDirectives,\n    });\n  }\n\n  private load(context: PlaylistLoaderContext): void {\n    const config = this.hls.config;\n\n    // logger.debug(`[playlist-loader]: Loading playlist of type ${context.type}, level: ${context.level}, id: ${context.id}`);\n\n    // Check if a loader for this context already exists\n    let loader = this.getInternalLoader(context);\n    if (loader) {\n      const loaderContext = loader.context as PlaylistLoaderContext;\n      if (\n        loaderContext &&\n        loaderContext.url === context.url &&\n        loaderContext.level === context.level\n      ) {\n        // same URL can't overlap\n        logger.trace('[playlist-loader]: playlist request ongoing');\n        return;\n      }\n      logger.log(\n        `[playlist-loader]: aborting previous loader for type: ${context.type}`,\n      );\n      loader.abort();\n    }\n\n    // apply different configs for retries depending on\n    // context (manifest, level, audio/subs playlist)\n    let loadPolicy: LoaderConfig;\n    if (context.type === PlaylistContextType.MANIFEST) {\n      loadPolicy = config.manifestLoadPolicy.default;\n    } else {\n      loadPolicy = Object.assign({}, config.playlistLoadPolicy.default, {\n        timeoutRetry: null,\n        errorRetry: null,\n      });\n    }\n    loader = this.createInternalLoader(context);\n\n    // Override level/track timeout for LL-HLS requests\n    // (the default of 10000ms is counter productive to blocking playlist reload requests)\n    if (Number.isFinite(context.deliveryDirectives?.part)) {\n      let levelDetails: LevelDetails | undefined;\n      if (\n        context.type === PlaylistContextType.LEVEL &&\n        context.level !== null\n      ) {\n        levelDetails = this.hls.levels[context.level].details;\n      } else if (\n        context.type === PlaylistContextType.AUDIO_TRACK &&\n        context.id !== null\n      ) {\n        levelDetails = this.hls.audioTracks[context.id].details;\n      } else if (\n        context.type === PlaylistContextType.SUBTITLE_TRACK &&\n        context.id !== null\n      ) {\n        levelDetails = this.hls.subtitleTracks[context.id].details;\n      }\n      if (levelDetails) {\n        const partTarget = levelDetails.partTarget;\n        const targetDuration = levelDetails.targetduration;\n        if (partTarget && targetDuration) {\n          const maxLowLatencyPlaylistRefresh =\n            Math.max(partTarget * 3, targetDuration * 0.8) * 1000;\n          loadPolicy = Object.assign({}, loadPolicy, {\n            maxTimeToFirstByteMs: Math.min(\n              maxLowLatencyPlaylistRefresh,\n              loadPolicy.maxTimeToFirstByteMs,\n            ),\n            maxLoadTimeMs: Math.min(\n              maxLowLatencyPlaylistRefresh,\n              loadPolicy.maxTimeToFirstByteMs,\n            ),\n          });\n        }\n      }\n    }\n\n    const legacyRetryCompatibility: RetryConfig | Record<string, void> =\n      loadPolicy.errorRetry || loadPolicy.timeoutRetry || {};\n    const loaderConfig: LoaderConfiguration = {\n      loadPolicy,\n      timeout: loadPolicy.maxLoadTimeMs,\n      maxRetry: legacyRetryCompatibility.maxNumRetry || 0,\n      retryDelay: legacyRetryCompatibility.retryDelayMs || 0,\n      maxRetryDelay: legacyRetryCompatibility.maxRetryDelayMs || 0,\n    };\n\n    const loaderCallbacks: LoaderCallbacks<PlaylistLoaderContext> = {\n      onSuccess: (response, stats, context, networkDetails) => {\n        const loader = this.getInternalLoader(context) as\n          | Loader<PlaylistLoaderContext>\n          | undefined;\n        this.resetInternalLoader(context.type);\n\n        const string = response.data as string;\n\n        // Validate if it is an M3U8 at all\n        if (string.indexOf('#EXTM3U') !== 0) {\n          this.handleManifestParsingError(\n            response,\n            context,\n            new Error('no EXTM3U delimiter'),\n            networkDetails || null,\n            stats,\n          );\n          return;\n        }\n\n        stats.parsing.start = performance.now();\n        if (M3U8Parser.isMediaPlaylist(string)) {\n          this.handleTrackOrLevelPlaylist(\n            response,\n            stats,\n            context,\n            networkDetails || null,\n            loader,\n          );\n        } else {\n          this.handleMasterPlaylist(response, stats, context, networkDetails);\n        }\n      },\n      onError: (response, context, networkDetails, stats) => {\n        this.handleNetworkError(\n          context,\n          networkDetails,\n          false,\n          response,\n          stats,\n        );\n      },\n      onTimeout: (stats, context, networkDetails) => {\n        this.handleNetworkError(\n          context,\n          networkDetails,\n          true,\n          undefined,\n          stats,\n        );\n      },\n    };\n\n    // logger.debug(`[playlist-loader]: Calling internal loader delegate for URL: ${context.url}`);\n\n    loader.load(context, loaderConfig, loaderCallbacks);\n  }\n\n  private handleMasterPlaylist(\n    response: LoaderResponse,\n    stats: LoaderStats,\n    context: PlaylistLoaderContext,\n    networkDetails: any,\n  ): void {\n    const hls = this.hls;\n    const string = response.data as string;\n\n    const url = getResponseUrl(response, context);\n\n    const parsedResult = M3U8Parser.parseMasterPlaylist(string, url);\n\n    if (parsedResult.playlistParsingError) {\n      this.handleManifestParsingError(\n        response,\n        context,\n        parsedResult.playlistParsingError,\n        networkDetails,\n        stats,\n      );\n      return;\n    }\n\n    const {\n      contentSteering,\n      levels,\n      sessionData,\n      sessionKeys,\n      startTimeOffset,\n      variableList,\n    } = parsedResult;\n\n    this.variableList = variableList;\n\n    const {\n      AUDIO: audioTracks = [],\n      SUBTITLES: subtitles,\n      'CLOSED-CAPTIONS': captions,\n    } = M3U8Parser.parseMasterPlaylistMedia(string, url, parsedResult);\n\n    if (audioTracks.length) {\n      // check if we have found an audio track embedded in main playlist (audio track without URI attribute)\n      const embeddedAudioFound: boolean = audioTracks.some(\n        (audioTrack) => !audioTrack.url,\n      );\n\n      // if no embedded audio track defined, but audio codec signaled in quality level,\n      // we need to signal this main audio track this could happen with playlists with\n      // alt audio rendition in which quality levels (main)\n      // contains both audio+video. but with mixed audio track not signaled\n      if (\n        !embeddedAudioFound &&\n        levels[0].audioCodec &&\n        !levels[0].attrs.AUDIO\n      ) {\n        logger.log(\n          '[playlist-loader]: audio codec signaled in quality level, but no embedded audio track signaled, create one',\n        );\n        audioTracks.unshift({\n          type: 'main',\n          name: 'main',\n          groupId: 'main',\n          default: false,\n          autoselect: false,\n          forced: false,\n          id: -1,\n          attrs: new AttrList({}) as MediaAttributes,\n          bitrate: 0,\n          url: '',\n        });\n      }\n    }\n\n    hls.trigger(Events.MANIFEST_LOADED, {\n      levels,\n      audioTracks,\n      subtitles,\n      captions,\n      contentSteering,\n      url,\n      stats,\n      networkDetails,\n      sessionData,\n      sessionKeys,\n      startTimeOffset,\n      variableList,\n    });\n  }\n\n  private handleTrackOrLevelPlaylist(\n    response: LoaderResponse,\n    stats: LoaderStats,\n    context: PlaylistLoaderContext,\n    networkDetails: any,\n    loader: Loader<PlaylistLoaderContext> | undefined,\n  ): void {\n    const hls = this.hls;\n    const { id, level, type } = context;\n\n    const url = getResponseUrl(response, context);\n    const levelUrlId = 0;\n    const levelId = Number.isFinite(level as number)\n      ? (level as number)\n      : Number.isFinite(id as number)\n        ? (id as number)\n        : 0;\n    const levelType = mapContextToLevelType(context);\n    const levelDetails: LevelDetails = M3U8Parser.parseLevelPlaylist(\n      response.data as string,\n      url,\n      levelId,\n      levelType,\n      levelUrlId,\n      this.variableList,\n    );\n\n    // We have done our first request (Manifest-type) and receive\n    // not a master playlist but a chunk-list (track/level)\n    // We fire the manifest-loaded event anyway with the parsed level-details\n    // by creating a single-level structure for it.\n    if (type === PlaylistContextType.MANIFEST) {\n      const singleLevel: LevelParsed = {\n        attrs: new AttrList({}),\n        bitrate: 0,\n        details: levelDetails,\n        name: '',\n        url,\n      };\n\n      hls.trigger(Events.MANIFEST_LOADED, {\n        levels: [singleLevel],\n        audioTracks: [],\n        url,\n        stats,\n        networkDetails,\n        sessionData: null,\n        sessionKeys: null,\n        contentSteering: null,\n        startTimeOffset: null,\n        variableList: null,\n      });\n    }\n\n    // save parsing time\n    stats.parsing.end = performance.now();\n\n    // extend the context with the new levelDetails property\n    context.levelDetails = levelDetails;\n\n    this.handlePlaylistLoaded(\n      levelDetails,\n      response,\n      stats,\n      context,\n      networkDetails,\n      loader,\n    );\n  }\n\n  private handleManifestParsingError(\n    response: LoaderResponse,\n    context: PlaylistLoaderContext,\n    error: Error,\n    networkDetails: any,\n    stats: LoaderStats,\n  ): void {\n    this.hls.trigger(Events.ERROR, {\n      type: ErrorTypes.NETWORK_ERROR,\n      details: ErrorDetails.MANIFEST_PARSING_ERROR,\n      fatal: context.type === PlaylistContextType.MANIFEST,\n      url: response.url,\n      err: error,\n      error,\n      reason: error.message,\n      response,\n      context,\n      networkDetails,\n      stats,\n    });\n  }\n\n  private handleNetworkError(\n    context: PlaylistLoaderContext,\n    networkDetails: any,\n    timeout = false,\n    response: { code: number; text: string } | undefined,\n    stats: LoaderStats,\n  ): void {\n    let message = `A network ${\n      timeout\n        ? 'timeout'\n        : 'error' + (response ? ' (status ' + response.code + ')' : '')\n    } occurred while loading ${context.type}`;\n    if (context.type === PlaylistContextType.LEVEL) {\n      message += `: ${context.level} id: ${context.id}`;\n    } else if (\n      context.type === PlaylistContextType.AUDIO_TRACK ||\n      context.type === PlaylistContextType.SUBTITLE_TRACK\n    ) {\n      message += ` id: ${context.id} group-id: \"${context.groupId}\"`;\n    }\n    const error = new Error(message);\n    logger.warn(`[playlist-loader]: ${message}`);\n    let details = ErrorDetails.UNKNOWN;\n    let fatal = false;\n\n    const loader = this.getInternalLoader(context);\n\n    switch (context.type) {\n      case PlaylistContextType.MANIFEST:\n        details = timeout\n          ? ErrorDetails.MANIFEST_LOAD_TIMEOUT\n          : ErrorDetails.MANIFEST_LOAD_ERROR;\n        fatal = true;\n        break;\n      case PlaylistContextType.LEVEL:\n        details = timeout\n          ? ErrorDetails.LEVEL_LOAD_TIMEOUT\n          : ErrorDetails.LEVEL_LOAD_ERROR;\n        fatal = false;\n        break;\n      case PlaylistContextType.AUDIO_TRACK:\n        details = timeout\n          ? ErrorDetails.AUDIO_TRACK_LOAD_TIMEOUT\n          : ErrorDetails.AUDIO_TRACK_LOAD_ERROR;\n        fatal = false;\n        break;\n      case PlaylistContextType.SUBTITLE_TRACK:\n        details = timeout\n          ? ErrorDetails.SUBTITLE_TRACK_LOAD_TIMEOUT\n          : ErrorDetails.SUBTITLE_LOAD_ERROR;\n        fatal = false;\n        break;\n    }\n\n    if (loader) {\n      this.resetInternalLoader(context.type);\n    }\n\n    const errorData: ErrorData = {\n      type: ErrorTypes.NETWORK_ERROR,\n      details,\n      fatal,\n      url: context.url,\n      loader,\n      context,\n      error,\n      networkDetails,\n      stats,\n    };\n\n    if (response) {\n      const url = networkDetails?.url || context.url;\n      errorData.response = { url, data: undefined as any, ...response };\n    }\n\n    this.hls.trigger(Events.ERROR, errorData);\n  }\n\n  private handlePlaylistLoaded(\n    levelDetails: LevelDetails,\n    response: LoaderResponse,\n    stats: LoaderStats,\n    context: PlaylistLoaderContext,\n    networkDetails: any,\n    loader: Loader<PlaylistLoaderContext> | undefined,\n  ): void {\n    const hls = this.hls;\n    const { type, level, id, groupId, deliveryDirectives } = context;\n    const url = getResponseUrl(response, context);\n    const parent = mapContextToLevelType(context);\n    const levelIndex =\n      typeof context.level === 'number' && parent === PlaylistLevelType.MAIN\n        ? (level as number)\n        : undefined;\n    if (!levelDetails.fragments.length) {\n      const error = new Error('No Segments found in Playlist');\n      hls.trigger(Events.ERROR, {\n        type: ErrorTypes.NETWORK_ERROR,\n        details: ErrorDetails.LEVEL_EMPTY_ERROR,\n        fatal: false,\n        url,\n        error,\n        reason: error.message,\n        response,\n        context,\n        level: levelIndex,\n        parent,\n        networkDetails,\n        stats,\n      });\n      return;\n    }\n    if (!levelDetails.targetduration) {\n      levelDetails.playlistParsingError = new Error('Missing Target Duration');\n    }\n    const error = levelDetails.playlistParsingError;\n    if (error) {\n      hls.trigger(Events.ERROR, {\n        type: ErrorTypes.NETWORK_ERROR,\n        details: ErrorDetails.LEVEL_PARSING_ERROR,\n        fatal: false,\n        url,\n        error,\n        reason: error.message,\n        response,\n        context,\n        level: levelIndex,\n        parent,\n        networkDetails,\n        stats,\n      });\n      return;\n    }\n\n    if (levelDetails.live && loader) {\n      if (loader.getCacheAge) {\n        levelDetails.ageHeader = loader.getCacheAge() || 0;\n      }\n      if (!loader.getCacheAge || isNaN(levelDetails.ageHeader)) {\n        levelDetails.ageHeader = 0;\n      }\n    }\n\n    switch (type) {\n      case PlaylistContextType.MANIFEST:\n      case PlaylistContextType.LEVEL:\n        hls.trigger(Events.LEVEL_LOADED, {\n          details: levelDetails,\n          level: levelIndex || 0,\n          id: id || 0,\n          stats,\n          networkDetails,\n          deliveryDirectives,\n        });\n        break;\n      case PlaylistContextType.AUDIO_TRACK:\n        hls.trigger(Events.AUDIO_TRACK_LOADED, {\n          details: levelDetails,\n          id: id || 0,\n          groupId: groupId || '',\n          stats,\n          networkDetails,\n          deliveryDirectives,\n        });\n        break;\n      case PlaylistContextType.SUBTITLE_TRACK:\n        hls.trigger(Events.SUBTITLE_TRACK_LOADED, {\n          details: levelDetails,\n          id: id || 0,\n          groupId: groupId || '',\n          stats,\n          networkDetails,\n          deliveryDirectives,\n        });\n        break;\n    }\n  }\n}\n\nexport default PlaylistLoader;\n", "import { logger } from './logger';\n\nexport function sendAddTrackEvent(track: TextTrack, videoEl: HTMLMediaElement) {\n  let event: Event;\n  try {\n    event = new Event('addtrack');\n  } catch (err) {\n    // for IE11\n    event = document.createEvent('Event');\n    event.initEvent('addtrack', false, false);\n  }\n  (event as any).track = track;\n  videoEl.dispatchEvent(event);\n}\n\nexport function addCueToTrack(track: TextTrack, cue: VTTCue) {\n  // Sometimes there are cue overlaps on segmented vtts so the same\n  // cue can appear more than once in different vtt files.\n  // This avoid showing duplicated cues with same timecode and text.\n  const mode = track.mode;\n  if (mode === 'disabled') {\n    track.mode = 'hidden';\n  }\n  if (track.cues && !track.cues.getCueById(cue.id)) {\n    try {\n      track.addCue(cue);\n      if (!track.cues.getCueById(cue.id)) {\n        throw new Error(`addCue is failed for: ${cue}`);\n      }\n    } catch (err) {\n      logger.debug(`[texttrack-utils]: ${err}`);\n      try {\n        const textTrackCue = new (self.TextTrackCue as any)(\n          cue.startTime,\n          cue.endTime,\n          cue.text,\n        );\n        textTrackCue.id = cue.id;\n        track.addCue(textTrackCue);\n      } catch (err2) {\n        logger.debug(\n          `[texttrack-utils]: Legacy TextTrackCue fallback failed: ${err2}`,\n        );\n      }\n    }\n  }\n  if (mode === 'disabled') {\n    track.mode = mode;\n  }\n}\n\nexport function clearCurrentCues(track: TextTrack) {\n  // When track.mode is disabled, track.cues will be null.\n  // To guarantee the removal of cues, we need to temporarily\n  // change the mode to hidden\n  const mode = track.mode;\n  if (mode === 'disabled') {\n    track.mode = 'hidden';\n  }\n  if (track.cues) {\n    for (let i = track.cues.length; i--; ) {\n      track.removeCue(track.cues[i]);\n    }\n  }\n  if (mode === 'disabled') {\n    track.mode = mode;\n  }\n}\n\nexport function removeCuesInRange(\n  track: TextTrack,\n  start: number,\n  end: number,\n  predicate?: (cue: TextTrackCue) => boolean,\n) {\n  const mode = track.mode;\n  if (mode === 'disabled') {\n    track.mode = 'hidden';\n  }\n\n  if (track.cues && track.cues.length > 0) {\n    const cues = getCuesInRange(track.cues, start, end);\n    for (let i = 0; i < cues.length; i++) {\n      if (!predicate || predicate(cues[i])) {\n        track.removeCue(cues[i]);\n      }\n    }\n  }\n  if (mode === 'disabled') {\n    track.mode = mode;\n  }\n}\n\n// Find first cue starting after given time.\n// Modified version of binary search O(log(n)).\nfunction getFirstCueIndexAfterTime(\n  cues: TextTrackCueList | TextTrackCue[],\n  time: number,\n): number {\n  // If first cue starts after time, start there\n  if (time < cues[0].startTime) {\n    return 0;\n  }\n  // If the last cue ends before time there is no overlap\n  const len = cues.length - 1;\n  if (time > cues[len].endTime) {\n    return -1;\n  }\n\n  let left = 0;\n  let right = len;\n\n  while (left <= right) {\n    const mid = Math.floor((right + left) / 2);\n\n    if (time < cues[mid].startTime) {\n      right = mid - 1;\n    } else if (time > cues[mid].startTime && left < len) {\n      left = mid + 1;\n    } else {\n      // If it's not lower or higher, it must be equal.\n      return mid;\n    }\n  }\n  // At this point, left and right have swapped.\n  // No direct match was found, left or right element must be the closest. Check which one has the smallest diff.\n  return cues[left].startTime - time < time - cues[right].startTime\n    ? left\n    : right;\n}\n\nexport function getCuesInRange(\n  cues: TextTrackCueList | TextTrackCue[],\n  start: number,\n  end: number,\n): TextTrackCue[] {\n  const cuesFound: TextTrackCue[] = [];\n  const firstCueInRange = getFirstCueIndexAfterTime(cues, start);\n  if (firstCueInRange > -1) {\n    for (let i = firstCueInRange, len = cues.length; i < len; i++) {\n      const cue = cues[i];\n      if (cue.startTime >= start && cue.endTime <= end) {\n        cuesFound.push(cue);\n      } else if (cue.startTime > end) {\n        return cuesFound;\n      }\n    }\n  }\n  return cuesFound;\n}\n\nexport function filterSubtitleTracks(\n  textTrackList: TextTrackList,\n): TextTrack[] {\n  const tracks: TextTrack[] = [];\n  for (let i = 0; i < textTrackList.length; i++) {\n    const track = textTrackList[i];\n    // Edge adds a track without a label; we don't want to use it\n    if (\n      (track.kind === 'subtitles' || track.kind === 'captions') &&\n      track.label\n    ) {\n      tracks.push(textTrackList[i]);\n    }\n  }\n  return tracks;\n}\n", "import type { RationalTimestamp } from '../utils/timescale-conversion';\n\nexport interface Demuxer {\n  demux(\n    data: Uint8Array,\n    timeOffset: number,\n    isSampleAes?: boolean,\n    flush?: boolean,\n  ): DemuxerResult;\n  demuxSampleAes(\n    data: Uint8Array,\n    keyData: KeyData,\n    timeOffset: number,\n  ): Promise<DemuxerResult>;\n  flush(timeOffset?: number): DemuxerResult | Promise<DemuxerResult>;\n  destroy(): void;\n  resetInitSegment(\n    initSegment: Uint8Array | undefined,\n    audioCodec: string | undefined,\n    videoCodec: string | undefined,\n    trackDuration: number,\n  );\n  resetTimeStamp(defaultInitPTS?: RationalTimestamp | null): void;\n  resetContiguity(): void;\n}\n\nexport interface DemuxerResult {\n  audioTrack: DemuxedAudioTrack;\n  videoTrack: DemuxedVideoTrackBase;\n  id3Track: DemuxedMetadataTrack;\n  textTrack: DemuxedUserdataTrack;\n}\n\nexport interface DemuxedTrack {\n  type: string;\n  id: number;\n  pid: number;\n  inputTimeScale: number;\n  sequenceNumber: number;\n  samples:\n    | AudioSample[]\n    | VideoSample[]\n    | MetadataSample[]\n    | UserdataSample[]\n    | Uint8Array;\n  timescale?: number;\n  container?: string;\n  dropped: number;\n  duration?: number;\n  pesData?: ElementaryStreamData | null;\n  codec?: string;\n}\n\nexport interface PassthroughTrack extends DemuxedTrack {\n  sampleDuration: number;\n  samples: Uint8Array;\n  timescale: number;\n  duration: number;\n  codec: string;\n}\nexport interface DemuxedAudioTrack extends DemuxedTrack {\n  config?: number[] | Uint8Array;\n  samplerate?: number;\n  segmentCodec?: string;\n  channelCount?: number;\n  manifestCodec?: string;\n  samples: AudioSample[];\n}\n\nexport interface DemuxedVideoTrackBase extends DemuxedTrack {\n  width?: number;\n  height?: number;\n  pixelRatio?: [number, number];\n  audFound?: boolean;\n  pps?: Uint8Array[];\n  sps?: Uint8Array[];\n  naluState?: number;\n  segmentCodec?: string;\n  manifestCodec?: string;\n  samples: VideoSample[] | Uint8Array;\n}\n\nexport interface DemuxedVideoTrack extends DemuxedVideoTrackBase {\n  samples: VideoSample[];\n}\n\nexport interface DemuxedMetadataTrack extends DemuxedTrack {\n  samples: MetadataSample[];\n}\n\nexport interface DemuxedUserdataTrack extends DemuxedTrack {\n  samples: UserdataSample[];\n}\n\nexport const enum MetadataSchema {\n  audioId3 = 'org.id3',\n  dateRange = 'com.apple.quicktime.HLS',\n  emsg = 'https://aomedia.org/emsg/ID3',\n}\nexport interface MetadataSample {\n  pts: number;\n  dts: number;\n  duration: number;\n  len?: number;\n  data: Uint8Array;\n  type: MetadataSchema;\n}\n\nexport interface UserdataSample {\n  pts: number;\n  bytes?: Uint8Array;\n  type?: number;\n  payloadType?: number;\n  uuid?: string;\n  userData?: string;\n  userDataBytes?: Uint8Array;\n}\n\nexport interface VideoSample {\n  dts: number;\n  pts: number;\n  key: boolean;\n  frame: boolean;\n  units: VideoSampleUnit[];\n  debug: string;\n  length: number;\n}\n\nexport interface VideoSampleUnit {\n  data: Uint8Array;\n  type: number;\n  state?: number;\n}\n\nexport type AudioSample = {\n  unit: Uint8Array;\n  pts: number;\n};\n\nexport type AudioFrame = {\n  sample: AudioSample;\n  length: number;\n  missing: number;\n};\n\nexport interface ElementaryStreamData {\n  data: Uint8Array[];\n  size: number;\n}\n\nexport interface KeyData {\n  method: string;\n  key: Uint8Array;\n  iv: Uint8Array;\n}\n", "import { Events } from '../events';\nimport {\n  sendAddTrackEvent,\n  clearCurrentCues,\n  removeCuesInRange,\n} from '../utils/texttrack-utils';\nimport * as ID3 from '../demux/id3';\nimport {\n  DateRange,\n  isDateRangeCueAttribute,\n  isSCTE35Attribute,\n} from '../loader/date-range';\nimport { MetadataSchema } from '../types/demuxer';\nimport type {\n  BufferFlushingData,\n  FragParsingMetadataData,\n  LevelUpdatedData,\n  MediaAttachedData,\n} from '../types/events';\nimport type { ComponentAPI } from '../types/component-api';\nimport type Hls from '../hls';\n\ndeclare global {\n  interface Window {\n    WebKitDataCue: VTTCue | void;\n  }\n}\n\nconst MIN_CUE_DURATION = 0.25;\n\nfunction getCueClass(): typeof VTTCue | typeof TextTrackCue | undefined {\n  if (typeof self === 'undefined') return undefined;\n  return self.VTTCue || self.TextTrackCue;\n}\n\nfunction createCueWithDataFields(\n  Cue: typeof VTTCue | typeof TextTrackCue,\n  startTime: number,\n  endTime: number,\n  data: Object,\n  type?: string,\n): VTTCue | TextTrackCue | undefined {\n  let cue = new Cue(startTime, endTime, '');\n  try {\n    (cue as any).value = data;\n    if (type) {\n      (cue as any).type = type;\n    }\n  } catch (e) {\n    cue = new Cue(\n      startTime,\n      endTime,\n      JSON.stringify(type ? { type, ...data } : data),\n    );\n  }\n  return cue;\n}\n\n// VTTCue latest draft allows an infinite duration, fallback\n// to MAX_VALUE if necessary\nconst MAX_CUE_ENDTIME = (() => {\n  const Cue = getCueClass();\n  try {\n    Cue && new Cue(0, Number.POSITIVE_INFINITY, '');\n  } catch (e) {\n    return Number.MAX_VALUE;\n  }\n  return Number.POSITIVE_INFINITY;\n})();\n\nfunction dateRangeDateToTimelineSeconds(date: Date, offset: number): number {\n  return date.getTime() / 1000 - offset;\n}\n\nfunction hexToArrayBuffer(str): ArrayBuffer {\n  return Uint8Array.from(\n    str\n      .replace(/^0x/, '')\n      .replace(/([\\da-fA-F]{2}) ?/g, '0x$1 ')\n      .replace(/ +$/, '')\n      .split(' '),\n  ).buffer;\n}\nclass ID3TrackController implements ComponentAPI {\n  private hls: Hls;\n  private id3Track: TextTrack | null = null;\n  private media: HTMLMediaElement | null = null;\n  private dateRangeCuesAppended: Record<\n    string,\n    {\n      cues: Record<string, VTTCue | TextTrackCue>;\n      dateRange: DateRange;\n      durationKnown: boolean;\n    }\n  > = {};\n\n  constructor(hls) {\n    this.hls = hls;\n    this._registerListeners();\n  }\n\n  destroy() {\n    this._unregisterListeners();\n    this.id3Track = null;\n    this.media = null;\n    this.dateRangeCuesAppended = {};\n    // @ts-ignore\n    this.hls = null;\n  }\n\n  private _registerListeners() {\n    const { hls } = this;\n    hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n    hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n    hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    hls.on(Events.FRAG_PARSING_METADATA, this.onFragParsingMetadata, this);\n    hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);\n    hls.on(Events.LEVEL_UPDATED, this.onLevelUpdated, this);\n  }\n\n  private _unregisterListeners() {\n    const { hls } = this;\n    hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n    hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n    hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    hls.off(Events.FRAG_PARSING_METADATA, this.onFragParsingMetadata, this);\n    hls.off(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);\n    hls.off(Events.LEVEL_UPDATED, this.onLevelUpdated, this);\n  }\n\n  // Add ID3 metatadata text track.\n  protected onMediaAttached(\n    event: Events.MEDIA_ATTACHED,\n    data: MediaAttachedData,\n  ): void {\n    this.media = data.media;\n  }\n\n  protected onMediaDetaching(): void {\n    if (!this.id3Track) {\n      return;\n    }\n    clearCurrentCues(this.id3Track);\n    this.id3Track = null;\n    this.media = null;\n    this.dateRangeCuesAppended = {};\n  }\n\n  private onManifestLoading() {\n    this.dateRangeCuesAppended = {};\n  }\n\n  createTrack(media: HTMLMediaElement): TextTrack {\n    const track = this.getID3Track(media.textTracks) as TextTrack;\n    track.mode = 'hidden';\n    return track;\n  }\n\n  getID3Track(textTracks: TextTrackList): TextTrack | void {\n    if (!this.media) {\n      return;\n    }\n    for (let i = 0; i < textTracks.length; i++) {\n      const textTrack: TextTrack = textTracks[i];\n      if (textTrack.kind === 'metadata' && textTrack.label === 'id3') {\n        // send 'addtrack' when reusing the textTrack for metadata,\n        // same as what we do for captions\n        sendAddTrackEvent(textTrack, this.media);\n\n        return textTrack;\n      }\n    }\n    return this.media.addTextTrack('metadata', 'id3');\n  }\n\n  onFragParsingMetadata(\n    event: Events.FRAG_PARSING_METADATA,\n    data: FragParsingMetadataData,\n  ) {\n    if (!this.media) {\n      return;\n    }\n\n    const {\n      hls: {\n        config: { enableEmsgMetadataCues, enableID3MetadataCues },\n      },\n    } = this;\n    if (!enableEmsgMetadataCues && !enableID3MetadataCues) {\n      return;\n    }\n\n    const { samples } = data;\n\n    // create track dynamically\n    if (!this.id3Track) {\n      this.id3Track = this.createTrack(this.media);\n    }\n\n    const Cue = getCueClass();\n    if (!Cue) {\n      return;\n    }\n\n    for (let i = 0; i < samples.length; i++) {\n      const type = samples[i].type;\n      if (\n        (type === MetadataSchema.emsg && !enableEmsgMetadataCues) ||\n        !enableID3MetadataCues\n      ) {\n        continue;\n      }\n\n      const frames = ID3.getID3Frames(samples[i].data);\n      if (frames) {\n        const startTime = samples[i].pts;\n        let endTime: number = startTime + samples[i].duration;\n\n        if (endTime > MAX_CUE_ENDTIME) {\n          endTime = MAX_CUE_ENDTIME;\n        }\n\n        const timeDiff = endTime - startTime;\n        if (timeDiff <= 0) {\n          endTime = startTime + MIN_CUE_DURATION;\n        }\n\n        for (let j = 0; j < frames.length; j++) {\n          const frame = frames[j];\n          // Safari doesn't put the timestamp frame in the TextTrack\n          if (!ID3.isTimeStampFrame(frame)) {\n            // add a bounds to any unbounded cues\n            this.updateId3CueEnds(startTime, type);\n            const cue = createCueWithDataFields(\n              Cue,\n              startTime,\n              endTime,\n              frame,\n              type,\n            );\n            if (cue) {\n              this.id3Track.addCue(cue);\n            }\n          }\n        }\n      }\n    }\n  }\n\n  updateId3CueEnds(startTime: number, type: MetadataSchema) {\n    const cues = this.id3Track?.cues;\n    if (cues) {\n      for (let i = cues.length; i--; ) {\n        const cue = cues[i] as any;\n        if (\n          cue.type === type &&\n          cue.startTime < startTime &&\n          cue.endTime === MAX_CUE_ENDTIME\n        ) {\n          cue.endTime = startTime;\n        }\n      }\n    }\n  }\n\n  onBufferFlushing(\n    event: Events.BUFFER_FLUSHING,\n    { startOffset, endOffset, type }: BufferFlushingData,\n  ) {\n    const { id3Track, hls } = this;\n    if (!hls) {\n      return;\n    }\n\n    const {\n      config: { enableEmsgMetadataCues, enableID3MetadataCues },\n    } = hls;\n    if (id3Track && (enableEmsgMetadataCues || enableID3MetadataCues)) {\n      let predicate;\n\n      if (type === 'audio') {\n        predicate = (cue) =>\n          (cue as any).type === MetadataSchema.audioId3 &&\n          enableID3MetadataCues;\n      } else if (type === 'video') {\n        predicate = (cue) =>\n          (cue as any).type === MetadataSchema.emsg && enableEmsgMetadataCues;\n      } else {\n        predicate = (cue) =>\n          ((cue as any).type === MetadataSchema.audioId3 &&\n            enableID3MetadataCues) ||\n          ((cue as any).type === MetadataSchema.emsg && enableEmsgMetadataCues);\n      }\n      removeCuesInRange(id3Track, startOffset, endOffset, predicate);\n    }\n  }\n\n  onLevelUpdated(event: Events.LEVEL_UPDATED, { details }: LevelUpdatedData) {\n    if (\n      !this.media ||\n      !details.hasProgramDateTime ||\n      !this.hls.config.enableDateRangeMetadataCues\n    ) {\n      return;\n    }\n    const { dateRangeCuesAppended, id3Track } = this;\n    const { dateRanges } = details;\n    const ids = Object.keys(dateRanges);\n    // Remove cues from track not found in details.dateRanges\n    if (id3Track) {\n      const idsToRemove = Object.keys(dateRangeCuesAppended).filter(\n        (id) => !ids.includes(id),\n      );\n      for (let i = idsToRemove.length; i--; ) {\n        const id = idsToRemove[i];\n        Object.keys(dateRangeCuesAppended[id].cues).forEach((key) => {\n          id3Track.removeCue(dateRangeCuesAppended[id].cues[key]);\n        });\n        delete dateRangeCuesAppended[id];\n      }\n    }\n    // Exit if the playlist does not have Date Ranges or does not have Program Date Time\n    const lastFragment = details.fragments[details.fragments.length - 1];\n    if (ids.length === 0 || !Number.isFinite(lastFragment?.programDateTime)) {\n      return;\n    }\n\n    if (!this.id3Track) {\n      this.id3Track = this.createTrack(this.media);\n    }\n\n    const dateTimeOffset =\n      (lastFragment.programDateTime as number) / 1000 - lastFragment.start;\n    const Cue = getCueClass();\n\n    for (let i = 0; i < ids.length; i++) {\n      const id = ids[i];\n      const dateRange = dateRanges[id];\n      const startTime = dateRangeDateToTimelineSeconds(\n        dateRange.startDate,\n        dateTimeOffset,\n      );\n\n      // Process DateRanges to determine end-time (known DURATION, END-DATE, or END-ON-NEXT)\n      const appendedDateRangeCues = dateRangeCuesAppended[id];\n      const cues = appendedDateRangeCues?.cues || {};\n      let durationKnown = appendedDateRangeCues?.durationKnown || false;\n      let endTime = MAX_CUE_ENDTIME;\n      const endDate = dateRange.endDate;\n      if (endDate) {\n        endTime = dateRangeDateToTimelineSeconds(endDate, dateTimeOffset);\n        durationKnown = true;\n      } else if (dateRange.endOnNext && !durationKnown) {\n        const nextDateRangeWithSameClass = ids.reduce(\n          (candidateDateRange: DateRange | null, id) => {\n            if (id !== dateRange.id) {\n              const otherDateRange = dateRanges[id];\n              if (\n                otherDateRange.class === dateRange.class &&\n                otherDateRange.startDate > dateRange.startDate &&\n                (!candidateDateRange ||\n                  dateRange.startDate < candidateDateRange.startDate)\n              ) {\n                return otherDateRange;\n              }\n            }\n            return candidateDateRange;\n          },\n          null,\n        );\n        if (nextDateRangeWithSameClass) {\n          endTime = dateRangeDateToTimelineSeconds(\n            nextDateRangeWithSameClass.startDate,\n            dateTimeOffset,\n          );\n          durationKnown = true;\n        }\n      }\n\n      // Create TextTrack Cues for each MetadataGroup Item (select DateRange attribute)\n      // This is to emulate Safari HLS playback handling of DateRange tags\n      const attributes = Object.keys(dateRange.attr);\n      for (let j = 0; j < attributes.length; j++) {\n        const key = attributes[j];\n        if (!isDateRangeCueAttribute(key)) {\n          continue;\n        }\n        const cue = cues[key];\n        if (cue) {\n          if (durationKnown && !appendedDateRangeCues.durationKnown) {\n            cue.endTime = endTime;\n          }\n        } else if (Cue) {\n          let data = dateRange.attr[key];\n          if (isSCTE35Attribute(key)) {\n            data = hexToArrayBuffer(data);\n          }\n          const cue = createCueWithDataFields(\n            Cue,\n            startTime,\n            endTime,\n            { key, data },\n            MetadataSchema.dateRange,\n          );\n          if (cue) {\n            cue.id = id;\n            this.id3Track.addCue(cue);\n            cues[key] = cue;\n          }\n        }\n      }\n\n      // Keep track of processed DateRanges by ID for updating cues with new DateRange tag attributes\n      dateRangeCuesAppended[id] = {\n        cues,\n        dateRange,\n        durationKnown,\n      };\n    }\n  }\n}\n\nexport default ID3TrackController;\n", "import { LevelDetails } from '../loader/level-details';\nimport { ErrorDetails } from '../errors';\nimport { Events } from '../events';\nimport type {\n  ErrorData,\n  LevelUpdatedData,\n  MediaAttachingData,\n} from '../types/events';\nimport { logger } from '../utils/logger';\nimport type { ComponentAPI } from '../types/component-api';\nimport type Hls from '../hls';\nimport type { HlsConfig } from '../config';\n\nexport default class LatencyController implements ComponentAPI {\n  private hls: Hls;\n  private readonly config: HlsConfig;\n  private media: HTMLMediaElement | null = null;\n  private levelDetails: LevelDetails | null = null;\n  private currentTime: number = 0;\n  private stallCount: number = 0;\n  private _latency: number | null = null;\n  private timeupdateHandler = () => this.timeupdate();\n\n  constructor(hls: Hls) {\n    this.hls = hls;\n    this.config = hls.config;\n    this.registerListeners();\n  }\n\n  get latency(): number {\n    return this._latency || 0;\n  }\n\n  get maxLatency(): number {\n    const { config, levelDetails } = this;\n    if (config.liveMaxLatencyDuration !== undefined) {\n      return config.liveMaxLatencyDuration;\n    }\n    return levelDetails\n      ? config.liveMaxLatencyDurationCount * levelDetails.targetduration\n      : 0;\n  }\n\n  get targetLatency(): number | null {\n    const { levelDetails } = this;\n    if (levelDetails === null) {\n      return null;\n    }\n    const { holdBack, partHoldBack, targetduration } = levelDetails;\n    const { liveSyncDuration, liveSyncDurationCount, lowLatencyMode } =\n      this.config;\n    const userConfig = this.hls.userConfig;\n    let targetLatency = lowLatencyMode ? partHoldBack || holdBack : holdBack;\n    if (\n      userConfig.liveSyncDuration ||\n      userConfig.liveSyncDurationCount ||\n      targetLatency === 0\n    ) {\n      targetLatency =\n        liveSyncDuration !== undefined\n          ? liveSyncDuration\n          : liveSyncDurationCount * targetduration;\n    }\n    const maxLiveSyncOnStallIncrease = targetduration;\n    const liveSyncOnStallIncrease = 1.0;\n    return (\n      targetLatency +\n      Math.min(\n        this.stallCount * liveSyncOnStallIncrease,\n        maxLiveSyncOnStallIncrease,\n      )\n    );\n  }\n\n  get liveSyncPosition(): number | null {\n    const liveEdge = this.estimateLiveEdge();\n    const targetLatency = this.targetLatency;\n    const levelDetails = this.levelDetails;\n    if (liveEdge === null || targetLatency === null || levelDetails === null) {\n      return null;\n    }\n    const edge = levelDetails.edge;\n    const syncPosition = liveEdge - targetLatency - this.edgeStalled;\n    const min = edge - levelDetails.totalduration;\n    const max =\n      edge -\n      ((this.config.lowLatencyMode && levelDetails.partTarget) ||\n        levelDetails.targetduration);\n    return Math.min(Math.max(min, syncPosition), max);\n  }\n\n  get drift(): number {\n    const { levelDetails } = this;\n    if (levelDetails === null) {\n      return 1;\n    }\n    return levelDetails.drift;\n  }\n\n  get edgeStalled(): number {\n    const { levelDetails } = this;\n    if (levelDetails === null) {\n      return 0;\n    }\n    const maxLevelUpdateAge =\n      ((this.config.lowLatencyMode && levelDetails.partTarget) ||\n        levelDetails.targetduration) * 3;\n    return Math.max(levelDetails.age - maxLevelUpdateAge, 0);\n  }\n\n  private get forwardBufferLength(): number {\n    const { media, levelDetails } = this;\n    if (!media || !levelDetails) {\n      return 0;\n    }\n    const bufferedRanges = media.buffered.length;\n    return (\n      (bufferedRanges\n        ? media.buffered.end(bufferedRanges - 1)\n        : levelDetails.edge) - this.currentTime\n    );\n  }\n\n  public destroy(): void {\n    this.unregisterListeners();\n    this.onMediaDetaching();\n    this.levelDetails = null;\n    // @ts-ignore\n    this.hls = this.timeupdateHandler = null;\n  }\n\n  private registerListeners() {\n    this.hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n    this.hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n    this.hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    this.hls.on(Events.LEVEL_UPDATED, this.onLevelUpdated, this);\n    this.hls.on(Events.ERROR, this.onError, this);\n  }\n\n  private unregisterListeners() {\n    this.hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n    this.hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n    this.hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    this.hls.off(Events.LEVEL_UPDATED, this.onLevelUpdated, this);\n    this.hls.off(Events.ERROR, this.onError, this);\n  }\n\n  private onMediaAttached(\n    event: Events.MEDIA_ATTACHED,\n    data: MediaAttachingData,\n  ) {\n    this.media = data.media;\n    this.media.addEventListener('timeupdate', this.timeupdateHandler);\n  }\n\n  private onMediaDetaching() {\n    if (this.media) {\n      this.media.removeEventListener('timeupdate', this.timeupdateHandler);\n      this.media = null;\n    }\n  }\n\n  private onManifestLoading() {\n    this.levelDetails = null;\n    this._latency = null;\n    this.stallCount = 0;\n  }\n\n  private onLevelUpdated(\n    event: Events.LEVEL_UPDATED,\n    { details }: LevelUpdatedData,\n  ) {\n    this.levelDetails = details;\n    if (details.advanced) {\n      this.timeupdate();\n    }\n    if (!details.live && this.media) {\n      this.media.removeEventListener('timeupdate', this.timeupdateHandler);\n    }\n  }\n\n  private onError(event: Events.ERROR, data: ErrorData) {\n    if (data.details !== ErrorDetails.BUFFER_STALLED_ERROR) {\n      return;\n    }\n    this.stallCount++;\n    if (this.levelDetails?.live) {\n      logger.warn(\n        '[playback-rate-controller]: Stall detected, adjusting target latency',\n      );\n    }\n  }\n\n  private timeupdate() {\n    const { media, levelDetails } = this;\n    if (!media || !levelDetails) {\n      return;\n    }\n    this.currentTime = media.currentTime;\n\n    const latency = this.computeLatency();\n    if (latency === null) {\n      return;\n    }\n    this._latency = latency;\n\n    // Adapt playbackRate to meet target latency in low-latency mode\n    const { lowLatencyMode, maxLiveSyncPlaybackRate } = this.config;\n    if (\n      !lowLatencyMode ||\n      maxLiveSyncPlaybackRate === 1 ||\n      !levelDetails.live\n    ) {\n      return;\n    }\n    const targetLatency = this.targetLatency;\n    if (targetLatency === null) {\n      return;\n    }\n    const distanceFromTarget = latency - targetLatency;\n    // Only adjust playbackRate when within one target duration of targetLatency\n    // and more than one second from under-buffering.\n    // Playback further than one target duration from target can be considered DVR playback.\n    const liveMinLatencyDuration = Math.min(\n      this.maxLatency,\n      targetLatency + levelDetails.targetduration,\n    );\n    const inLiveRange = distanceFromTarget < liveMinLatencyDuration;\n\n    if (\n      inLiveRange &&\n      distanceFromTarget > 0.05 &&\n      this.forwardBufferLength > 1\n    ) {\n      const max = Math.min(2, Math.max(1.0, maxLiveSyncPlaybackRate));\n      const rate =\n        Math.round(\n          (2 / (1 + Math.exp(-0.75 * distanceFromTarget - this.edgeStalled))) *\n            20,\n        ) / 20;\n      media.playbackRate = Math.min(max, Math.max(1, rate));\n    } else if (media.playbackRate !== 1 && media.playbackRate !== 0) {\n      media.playbackRate = 1;\n    }\n  }\n\n  private estimateLiveEdge(): number | null {\n    const { levelDetails } = this;\n    if (levelDetails === null) {\n      return null;\n    }\n    return levelDetails.edge + levelDetails.age;\n  }\n\n  private computeLatency(): number | null {\n    const liveEdge = this.estimateLiveEdge();\n    if (liveEdge === null) {\n      return null;\n    }\n    return liveEdge - this.currentTime;\n  }\n}\n", "import type { MediaPlaylist } from './media-playlist';\nimport type { LevelDetails } from '../loader/level-details';\nimport type { AttrList } from '../utils/attr-list';\nimport type { MediaDecodingInfo } from '../utils/mediacapabilities-helper';\n\nexport interface LevelParsed {\n  attrs: LevelAttributes;\n  audioCodec?: string;\n  bitrate: number;\n  details?: LevelDetails;\n  height?: number;\n  id?: number;\n  name: string;\n  textCodec?: string;\n  unknownCodecs?: string[];\n  url: string;\n  videoCodec?: string;\n  width?: number;\n}\n\nexport interface LevelAttributes extends AttrList {\n  'ALLOWED-CPC'?: string;\n  AUDIO?: string;\n  'AVERAGE-BANDWIDTH'?: string;\n  BANDWIDTH?: string;\n  'CLOSED-CAPTIONS'?: string;\n  CODECS?: string;\n  'FRAME-RATE'?: string;\n  'HDCP-LEVEL'?: 'TYPE-0' | 'TYPE-1' | 'NONE';\n  'PATHWAY-ID'?: string;\n  RESOLUTION?: string;\n  SCORE?: string;\n  'STABLE-VARIANT-ID'?: string;\n  SUBTITLES?: string;\n  'SUPPLEMENTAL-CODECS'?: string;\n  VIDEO?: string;\n  'VIDEO-RANGE'?: VideoRange;\n}\n\nexport const HdcpLevels = ['NONE', 'TYPE-0', 'TYPE-1', null] as const;\nexport type HdcpLevel = (typeof HdcpLevels)[number];\n\nexport function isHdcpLevel(value: any): value is HdcpLevel {\n  return HdcpLevels.indexOf(value) > -1;\n}\n\nexport const VideoRangeValues = ['SDR', 'PQ', 'HLG'] as const;\nexport type VideoRange = (typeof VideoRangeValues)[number];\n\nexport function isVideoRange(value: any): value is VideoRange {\n  return !!value && VideoRangeValues.indexOf(value) > -1;\n}\n\nexport type VariableMap = Record<string, string>;\n\nexport const enum HlsSkip {\n  No = '',\n  Yes = 'YES',\n  v2 = 'v2',\n}\n\nexport function getSkipValue(details: LevelDetails): HlsSkip {\n  const { canSkipUntil, canSkipDateRanges, age } = details;\n  // A Client SHOULD NOT request a Playlist Delta Update unless it already\n  // has a version of the Playlist that is no older than one-half of the Skip Boundary.\n  // @see: https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis#section-6.3.7\n  const playlistRecentEnough = age < canSkipUntil / 2;\n  if (canSkipUntil && playlistRecentEnough) {\n    if (canSkipDateRanges) {\n      return HlsSkip.v2;\n    }\n    return HlsSkip.Yes;\n  }\n  return HlsSkip.No;\n}\n\nexport class HlsUrlParameters {\n  msn?: number;\n  part?: number;\n  skip?: HlsSkip;\n\n  constructor(msn?: number, part?: number, skip?: HlsSkip) {\n    this.msn = msn;\n    this.part = part;\n    this.skip = skip;\n  }\n\n  addDirectives(uri: string): string | never {\n    const url: URL = new self.URL(uri);\n    if (this.msn !== undefined) {\n      url.searchParams.set('_HLS_msn', this.msn.toString());\n    }\n    if (this.part !== undefined) {\n      url.searchParams.set('_HLS_part', this.part.toString());\n    }\n    if (this.skip) {\n      url.searchParams.set('_HLS_skip', this.skip);\n    }\n    return url.href;\n  }\n}\n\nexport class Level {\n  public readonly _attrs: LevelAttributes[];\n  public readonly audioCodec: string | undefined;\n  public readonly bitrate: number;\n  public readonly codecSet: string;\n  public readonly url: string[];\n  public readonly frameRate: number;\n  public readonly height: number;\n  public readonly id: number;\n  public readonly name: string;\n  public readonly videoCodec: string | undefined;\n  public readonly width: number;\n  public details?: LevelDetails;\n  public fragmentError: number = 0;\n  public loadError: number = 0;\n  public loaded?: { bytes: number; duration: number };\n  public realBitrate: number = 0;\n  public supportedPromise?: Promise<MediaDecodingInfo>;\n  public supportedResult?: MediaDecodingInfo;\n  private _avgBitrate: number = 0;\n  private _audioGroups?: (string | undefined)[];\n  private _subtitleGroups?: (string | undefined)[];\n  // Deprecated (retained for backwards compatibility)\n  private readonly _urlId: number = 0;\n\n  constructor(data: LevelParsed | MediaPlaylist) {\n    this.url = [data.url];\n    this._attrs = [data.attrs];\n    this.bitrate = data.bitrate;\n    if (data.details) {\n      this.details = data.details;\n    }\n    this.id = data.id || 0;\n    this.name = data.name;\n    this.width = data.width || 0;\n    this.height = data.height || 0;\n    this.frameRate = data.attrs.optionalFloat('FRAME-RATE', 0);\n    this._avgBitrate = data.attrs.decimalInteger('AVERAGE-BANDWIDTH');\n    this.audioCodec = data.audioCodec;\n    this.videoCodec = data.videoCodec;\n    this.codecSet = [data.videoCodec, data.audioCodec]\n      .filter((c) => !!c)\n      .map((s: string) => s.substring(0, 4))\n      .join(',');\n    this.addGroupId('audio', data.attrs.AUDIO);\n    this.addGroupId('text', data.attrs.SUBTITLES);\n  }\n\n  get maxBitrate(): number {\n    return Math.max(this.realBitrate, this.bitrate);\n  }\n\n  get averageBitrate(): number {\n    return this._avgBitrate || this.realBitrate || this.bitrate;\n  }\n\n  get attrs(): LevelAttributes {\n    return this._attrs[0];\n  }\n\n  get codecs(): string {\n    return this.attrs.CODECS || '';\n  }\n\n  get pathwayId(): string {\n    return this.attrs['PATHWAY-ID'] || '.';\n  }\n\n  get videoRange(): VideoRange {\n    return this.attrs['VIDEO-RANGE'] || 'SDR';\n  }\n\n  get score(): number {\n    return this.attrs.optionalFloat('SCORE', 0);\n  }\n\n  get uri(): string {\n    return this.url[0] || '';\n  }\n\n  hasAudioGroup(groupId: string | undefined): boolean {\n    return hasGroup(this._audioGroups, groupId);\n  }\n\n  hasSubtitleGroup(groupId: string | undefined): boolean {\n    return hasGroup(this._subtitleGroups, groupId);\n  }\n\n  get audioGroups(): (string | undefined)[] | undefined {\n    return this._audioGroups;\n  }\n\n  get subtitleGroups(): (string | undefined)[] | undefined {\n    return this._subtitleGroups;\n  }\n\n  addGroupId(type: string, groupId: string | undefined) {\n    if (!groupId) {\n      return;\n    }\n    if (type === 'audio') {\n      let audioGroups = this._audioGroups;\n      if (!audioGroups) {\n        audioGroups = this._audioGroups = [];\n      }\n      if (audioGroups.indexOf(groupId) === -1) {\n        audioGroups.push(groupId);\n      }\n    } else if (type === 'text') {\n      let subtitleGroups = this._subtitleGroups;\n      if (!subtitleGroups) {\n        subtitleGroups = this._subtitleGroups = [];\n      }\n      if (subtitleGroups.indexOf(groupId) === -1) {\n        subtitleGroups.push(groupId);\n      }\n    }\n  }\n\n  // Deprecated methods (retained for backwards compatibility)\n  get urlId(): number {\n    return 0;\n  }\n\n  set urlId(value: number) {}\n\n  get audioGroupIds(): (string | undefined)[] | undefined {\n    return this.audioGroups ? [this.audioGroupId] : undefined;\n  }\n\n  get textGroupIds(): (string | undefined)[] | undefined {\n    return this.subtitleGroups ? [this.textGroupId] : undefined;\n  }\n\n  get audioGroupId(): string | undefined {\n    return this.audioGroups?.[0];\n  }\n\n  get textGroupId(): string | undefined {\n    return this.subtitleGroups?.[0];\n  }\n\n  addFallback() {}\n}\n\nfunction hasGroup(\n  groups: (string | undefined)[] | undefined,\n  groupId: string | undefined,\n): boolean {\n  if (!groupId || !groups) {\n    return false;\n  }\n  return groups.indexOf(groupId) !== -1;\n}\n", "/**\n * Provides methods dealing with playlist sliding and drift\n */\n\nimport { logger } from './logger';\nimport { Fragment, Part } from '../loader/fragment';\nimport { LevelDetails } from '../loader/level-details';\nimport type { Level } from '../types/level';\nimport { DateRange } from '../loader/date-range';\n\ntype FragmentIntersection = (oldFrag: Fragment, newFrag: Fragment) => void;\ntype PartIntersection = (oldPart: Part, newPart: Part) => void;\n\nexport function updatePTS(\n  fragments: Fragment[],\n  fromIdx: number,\n  toIdx: number,\n): void {\n  const fragFrom = fragments[fromIdx];\n  const fragTo = fragments[toIdx];\n  updateFromToPTS(fragFrom, fragTo);\n}\n\nfunction updateFromToPTS(fragFrom: Fragment, fragTo: Fragment) {\n  const fragToPTS = fragTo.startPTS as number;\n  // if we know startPTS[toIdx]\n  if (Number.isFinite(fragToPTS)) {\n    // update fragment duration.\n    // it helps to fix drifts between playlist reported duration and fragment real duration\n    let duration: number = 0;\n    let frag: Fragment;\n    if (fragTo.sn > fragFrom.sn) {\n      duration = fragToPTS - fragFrom.start;\n      frag = fragFrom;\n    } else {\n      duration = fragFrom.start - fragToPTS;\n      frag = fragTo;\n    }\n    if (frag.duration !== duration) {\n      frag.duration = duration;\n    }\n    // we dont know startPTS[toIdx]\n  } else if (fragTo.sn > fragFrom.sn) {\n    const contiguous = fragFrom.cc === fragTo.cc;\n    // TODO: With part-loading end/durations we need to confirm the whole fragment is loaded before using (or setting) minEndPTS\n    if (contiguous && fragFrom.minEndPTS) {\n      fragTo.start = fragFrom.start + (fragFrom.minEndPTS - fragFrom.start);\n    } else {\n      fragTo.start = fragFrom.start + fragFrom.duration;\n    }\n  } else {\n    fragTo.start = Math.max(fragFrom.start - fragTo.duration, 0);\n  }\n}\n\nexport function updateFragPTSDTS(\n  details: LevelDetails | undefined,\n  frag: Fragment,\n  startPTS: number,\n  endPTS: number,\n  startDTS: number,\n  endDTS: number,\n): number {\n  const parsedMediaDuration = endPTS - startPTS;\n  if (parsedMediaDuration <= 0) {\n    logger.warn('Fragment should have a positive duration', frag);\n    endPTS = startPTS + frag.duration;\n    endDTS = startDTS + frag.duration;\n  }\n  let maxStartPTS = startPTS;\n  let minEndPTS = endPTS;\n  const fragStartPts = frag.startPTS as number;\n  const fragEndPts = frag.endPTS as number;\n  if (Number.isFinite(fragStartPts)) {\n    // delta PTS between audio and video\n    const deltaPTS = Math.abs(fragStartPts - startPTS);\n    if (!Number.isFinite(frag.deltaPTS as number)) {\n      frag.deltaPTS = deltaPTS;\n    } else {\n      frag.deltaPTS = Math.max(deltaPTS, frag.deltaPTS as number);\n    }\n\n    maxStartPTS = Math.max(startPTS, fragStartPts);\n    startPTS = Math.min(startPTS, fragStartPts);\n    startDTS = Math.min(startDTS, frag.startDTS);\n\n    minEndPTS = Math.min(endPTS, fragEndPts);\n    endPTS = Math.max(endPTS, fragEndPts);\n    endDTS = Math.max(endDTS, frag.endDTS);\n  }\n\n  const drift = startPTS - frag.start;\n  if (frag.start !== 0) {\n    frag.start = startPTS;\n  }\n  frag.duration = endPTS - frag.start;\n  frag.startPTS = startPTS;\n  frag.maxStartPTS = maxStartPTS;\n  frag.startDTS = startDTS;\n  frag.endPTS = endPTS;\n  frag.minEndPTS = minEndPTS;\n  frag.endDTS = endDTS;\n\n  const sn = frag.sn as number; // 'initSegment'\n  // exit if sn out of range\n  if (!details || sn < details.startSN || sn > details.endSN) {\n    return 0;\n  }\n  let i;\n  const fragIdx = sn - details.startSN;\n  const fragments = details.fragments;\n  // update frag reference in fragments array\n  // rationale is that fragments array might not contain this frag object.\n  // this will happen if playlist has been refreshed between frag loading and call to updateFragPTSDTS()\n  // if we don't update frag, we won't be able to propagate PTS info on the playlist\n  // resulting in invalid sliding computation\n  fragments[fragIdx] = frag;\n  // adjust fragment PTS/duration from seqnum-1 to frag 0\n  for (i = fragIdx; i > 0; i--) {\n    updateFromToPTS(fragments[i], fragments[i - 1]);\n  }\n\n  // adjust fragment PTS/duration from seqnum to last frag\n  for (i = fragIdx; i < fragments.length - 1; i++) {\n    updateFromToPTS(fragments[i], fragments[i + 1]);\n  }\n  if (details.fragmentHint) {\n    updateFromToPTS(fragments[fragments.length - 1], details.fragmentHint);\n  }\n\n  details.PTSKnown = details.alignedSliding = true;\n  return drift;\n}\n\nexport function mergeDetails(\n  oldDetails: LevelDetails,\n  newDetails: LevelDetails,\n): void {\n  // Track the last initSegment processed. Initialize it to the last one on the timeline.\n  let currentInitSegment: Fragment | null = null;\n  const oldFragments = oldDetails.fragments;\n  for (let i = oldFragments.length - 1; i >= 0; i--) {\n    const oldInit = oldFragments[i].initSegment;\n    if (oldInit) {\n      currentInitSegment = oldInit;\n      break;\n    }\n  }\n\n  if (oldDetails.fragmentHint) {\n    // prevent PTS and duration from being adjusted on the next hint\n    delete oldDetails.fragmentHint.endPTS;\n  }\n  // check if old/new playlists have fragments in common\n  // loop through overlapping SN and update startPTS , cc, and duration if any found\n  let ccOffset = 0;\n  let PTSFrag;\n  mapFragmentIntersection(\n    oldDetails,\n    newDetails,\n    (oldFrag: Fragment, newFrag: Fragment) => {\n      if (oldFrag.relurl) {\n        // Do not compare CC if the old fragment has no url. This is a level.fragmentHint used by LL-HLS parts.\n        // It maybe be off by 1 if it was created before any parts or discontinuity tags were appended to the end\n        // of the playlist.\n        ccOffset = oldFrag.cc - newFrag.cc;\n      }\n      if (\n        Number.isFinite(oldFrag.startPTS) &&\n        Number.isFinite(oldFrag.endPTS)\n      ) {\n        newFrag.start = newFrag.startPTS = oldFrag.startPTS as number;\n        newFrag.startDTS = oldFrag.startDTS;\n        newFrag.maxStartPTS = oldFrag.maxStartPTS;\n\n        newFrag.endPTS = oldFrag.endPTS;\n        newFrag.endDTS = oldFrag.endDTS;\n        newFrag.minEndPTS = oldFrag.minEndPTS;\n        newFrag.duration =\n          (oldFrag.endPTS as number) - (oldFrag.startPTS as number);\n\n        if (newFrag.duration) {\n          PTSFrag = newFrag;\n        }\n\n        // PTS is known when any segment has startPTS and endPTS\n        newDetails.PTSKnown = newDetails.alignedSliding = true;\n      }\n      newFrag.elementaryStreams = oldFrag.elementaryStreams;\n      newFrag.loader = oldFrag.loader;\n      newFrag.stats = oldFrag.stats;\n      if (oldFrag.initSegment) {\n        newFrag.initSegment = oldFrag.initSegment;\n        currentInitSegment = oldFrag.initSegment;\n      }\n    },\n  );\n\n  if (currentInitSegment) {\n    const fragmentsToCheck = newDetails.fragmentHint\n      ? newDetails.fragments.concat(newDetails.fragmentHint)\n      : newDetails.fragments;\n    fragmentsToCheck.forEach((frag) => {\n      if (\n        frag &&\n        (!frag.initSegment ||\n          frag.initSegment.relurl === currentInitSegment?.relurl)\n      ) {\n        frag.initSegment = currentInitSegment;\n      }\n    });\n  }\n\n  if (newDetails.skippedSegments) {\n    newDetails.deltaUpdateFailed = newDetails.fragments.some((frag) => !frag);\n    if (newDetails.deltaUpdateFailed) {\n      logger.warn(\n        '[level-helper] Previous playlist missing segments skipped in delta playlist',\n      );\n      for (let i = newDetails.skippedSegments; i--; ) {\n        newDetails.fragments.shift();\n      }\n      newDetails.startSN = newDetails.fragments[0].sn as number;\n      newDetails.startCC = newDetails.fragments[0].cc;\n    } else if (newDetails.canSkipDateRanges) {\n      newDetails.dateRanges = mergeDateRanges(\n        oldDetails.dateRanges,\n        newDetails.dateRanges,\n        newDetails.recentlyRemovedDateranges,\n      );\n    }\n  }\n\n  const newFragments = newDetails.fragments;\n  if (ccOffset) {\n    logger.warn('discontinuity sliding from playlist, take drift into account');\n    for (let i = 0; i < newFragments.length; i++) {\n      newFragments[i].cc += ccOffset;\n    }\n  }\n  if (newDetails.skippedSegments) {\n    newDetails.startCC = newDetails.fragments[0].cc;\n  }\n\n  // Merge parts\n  mapPartIntersection(\n    oldDetails.partList,\n    newDetails.partList,\n    (oldPart: Part, newPart: Part) => {\n      newPart.elementaryStreams = oldPart.elementaryStreams;\n      newPart.stats = oldPart.stats;\n    },\n  );\n\n  // if at least one fragment contains PTS info, recompute PTS information for all fragments\n  if (PTSFrag) {\n    updateFragPTSDTS(\n      newDetails,\n      PTSFrag,\n      PTSFrag.startPTS,\n      PTSFrag.endPTS,\n      PTSFrag.startDTS,\n      PTSFrag.endDTS,\n    );\n  } else {\n    // ensure that delta is within oldFragments range\n    // also adjust sliding in case delta is 0 (we could have old=[50-60] and new=old=[50-61])\n    // in that case we also need to adjust start offset of all fragments\n    adjustSliding(oldDetails, newDetails);\n  }\n\n  if (newFragments.length) {\n    newDetails.totalduration = newDetails.edge - newFragments[0].start;\n  }\n\n  newDetails.driftStartTime = oldDetails.driftStartTime;\n  newDetails.driftStart = oldDetails.driftStart;\n  const advancedDateTime = newDetails.advancedDateTime;\n  if (newDetails.advanced && advancedDateTime) {\n    const edge = newDetails.edge;\n    if (!newDetails.driftStart) {\n      newDetails.driftStartTime = advancedDateTime;\n      newDetails.driftStart = edge;\n    }\n    newDetails.driftEndTime = advancedDateTime;\n    newDetails.driftEnd = edge;\n  } else {\n    newDetails.driftEndTime = oldDetails.driftEndTime;\n    newDetails.driftEnd = oldDetails.driftEnd;\n    newDetails.advancedDateTime = oldDetails.advancedDateTime;\n  }\n}\n\nfunction mergeDateRanges(\n  oldDateRanges: Record<string, DateRange>,\n  deltaDateRanges: Record<string, DateRange>,\n  recentlyRemovedDateranges: string[] | undefined,\n): Record<string, DateRange> {\n  const dateRanges = Object.assign({}, oldDateRanges);\n  if (recentlyRemovedDateranges) {\n    recentlyRemovedDateranges.forEach((id) => {\n      delete dateRanges[id];\n    });\n  }\n  Object.keys(deltaDateRanges).forEach((id) => {\n    const dateRange = new DateRange(deltaDateRanges[id].attr, dateRanges[id]);\n    if (dateRange.isValid) {\n      dateRanges[id] = dateRange;\n    } else {\n      logger.warn(\n        `Ignoring invalid Playlist Delta Update DATERANGE tag: \"${JSON.stringify(\n          deltaDateRanges[id].attr,\n        )}\"`,\n      );\n    }\n  });\n  return dateRanges;\n}\n\nexport function mapPartIntersection(\n  oldParts: Part[] | null,\n  newParts: Part[] | null,\n  intersectionFn: PartIntersection,\n) {\n  if (oldParts && newParts) {\n    let delta = 0;\n    for (let i = 0, len = oldParts.length; i <= len; i++) {\n      const oldPart = oldParts[i];\n      const newPart = newParts[i + delta];\n      if (\n        oldPart &&\n        newPart &&\n        oldPart.index === newPart.index &&\n        oldPart.fragment.sn === newPart.fragment.sn\n      ) {\n        intersectionFn(oldPart, newPart);\n      } else {\n        delta--;\n      }\n    }\n  }\n}\n\nexport function mapFragmentIntersection(\n  oldDetails: LevelDetails,\n  newDetails: LevelDetails,\n  intersectionFn: FragmentIntersection,\n): void {\n  const skippedSegments = newDetails.skippedSegments;\n  const start =\n    Math.max(oldDetails.startSN, newDetails.startSN) - newDetails.startSN;\n  const end =\n    (oldDetails.fragmentHint ? 1 : 0) +\n    (skippedSegments\n      ? newDetails.endSN\n      : Math.min(oldDetails.endSN, newDetails.endSN)) -\n    newDetails.startSN;\n  const delta = newDetails.startSN - oldDetails.startSN;\n  const newFrags = newDetails.fragmentHint\n    ? newDetails.fragments.concat(newDetails.fragmentHint)\n    : newDetails.fragments;\n  const oldFrags = oldDetails.fragmentHint\n    ? oldDetails.fragments.concat(oldDetails.fragmentHint)\n    : oldDetails.fragments;\n\n  for (let i = start; i <= end; i++) {\n    const oldFrag = oldFrags[delta + i];\n    let newFrag = newFrags[i];\n    if (skippedSegments && !newFrag && i < skippedSegments) {\n      // Fill in skipped segments in delta playlist\n      newFrag = newDetails.fragments[i] = oldFrag;\n    }\n    if (oldFrag && newFrag) {\n      intersectionFn(oldFrag, newFrag);\n    }\n  }\n}\n\nexport function adjustSliding(\n  oldDetails: LevelDetails,\n  newDetails: LevelDetails,\n): void {\n  const delta =\n    newDetails.startSN + newDetails.skippedSegments - oldDetails.startSN;\n  const oldFragments = oldDetails.fragments;\n  if (delta < 0 || delta >= oldFragments.length) {\n    return;\n  }\n  addSliding(newDetails, oldFragments[delta].start);\n}\n\nexport function addSliding(details: LevelDetails, start: number) {\n  if (start) {\n    const fragments = details.fragments;\n    for (let i = details.skippedSegments; i < fragments.length; i++) {\n      fragments[i].start += start;\n    }\n    if (details.fragmentHint) {\n      details.fragmentHint.start += start;\n    }\n  }\n}\n\nexport function computeReloadInterval(\n  newDetails: LevelDetails,\n  distanceToLiveEdgeMs: number = Infinity,\n): number {\n  let reloadInterval = 1000 * newDetails.targetduration;\n\n  if (newDetails.updated) {\n    // Use last segment duration when shorter than target duration and near live edge\n    const fragments = newDetails.fragments;\n    const liveEdgeMaxTargetDurations = 4;\n    if (\n      fragments.length &&\n      reloadInterval * liveEdgeMaxTargetDurations > distanceToLiveEdgeMs\n    ) {\n      const lastSegmentDuration =\n        fragments[fragments.length - 1].duration * 1000;\n      if (lastSegmentDuration < reloadInterval) {\n        reloadInterval = lastSegmentDuration;\n      }\n    }\n  } else {\n    // estimate = 'miss half average';\n    // follow HLS Spec, If the client reloads a Playlist file and finds that it has not\n    // changed then it MUST wait for a period of one-half the target\n    // duration before retrying.\n    reloadInterval /= 2;\n  }\n\n  return Math.round(reloadInterval);\n}\n\nexport function getFragmentWithSN(\n  level: Level,\n  sn: number,\n  fragCurrent: Fragment | null,\n): Fragment | null {\n  if (!level?.details) {\n    return null;\n  }\n  const levelDetails = level.details;\n  let fragment: Fragment | undefined =\n    levelDetails.fragments[sn - levelDetails.startSN];\n  if (fragment) {\n    return fragment;\n  }\n  fragment = levelDetails.fragmentHint;\n  if (fragment && fragment.sn === sn) {\n    return fragment;\n  }\n  if (sn < levelDetails.startSN && fragCurrent && fragCurrent.sn === sn) {\n    return fragCurrent;\n  }\n  return null;\n}\n\nexport function getPartWith(\n  level: Level,\n  sn: number,\n  partIndex: number,\n): Part | null {\n  if (!level?.details) {\n    return null;\n  }\n  return findPart(level.details?.partList, sn, partIndex);\n}\n\nexport function findPart(\n  partList: Part[] | null | undefined,\n  sn: number,\n  partIndex: number,\n): Part | null {\n  if (partList) {\n    for (let i = partList.length; i--; ) {\n      const part = partList[i];\n      if (part.index === partIndex && part.fragment.sn === sn) {\n        return part;\n      }\n    }\n  }\n  return null;\n}\n\nexport function reassignFragmentLevelIndexes(levels: Level[]) {\n  levels.forEach((level, index) => {\n    const { details } = level;\n    if (details?.fragments) {\n      details.fragments.forEach((fragment) => {\n        fragment.level = index;\n      });\n    }\n  });\n}\n", "import { ErrorDetails } from '../errors';\nimport type { LoadPolicy, LoaderConfig, RetryConfig } from '../config';\nimport type { ErrorData } from '../types/events';\nimport type { LoaderResponse } from '../types/loader';\n\nexport function isTimeoutError(error: ErrorData): boolean {\n  switch (error.details) {\n    case ErrorDetails.FRAG_LOAD_TIMEOUT:\n    case ErrorDetails.KEY_LOAD_TIMEOUT:\n    case ErrorDetails.LEVEL_LOAD_TIMEOUT:\n    case ErrorDetails.MANIFEST_LOAD_TIMEOUT:\n      return true;\n  }\n  return false;\n}\n\nexport function getRetryConfig(\n  loadPolicy: LoadPolicy,\n  error: ErrorData,\n): RetryConfig | null {\n  const isTimeout = isTimeoutError(error);\n  return loadPolicy.default[`${isTimeout ? 'timeout' : 'error'}Retry`];\n}\n\nexport function getRetryDelay(\n  retryConfig: RetryConfig,\n  retryCount: number,\n): number {\n  // exponential backoff capped to max retry delay\n  const backoffFactor =\n    retryConfig.backoff === 'linear' ? 1 : Math.pow(2, retryCount);\n  return Math.min(\n    backoffFactor * retryConfig.retryDelayMs,\n    retryConfig.maxRetryDelayMs,\n  );\n}\n\nexport function getLoaderConfigWithoutReties(\n  loderConfig: LoaderConfig,\n): LoaderConfig {\n  return {\n    ...loderConfig,\n    ...{\n      errorRetry: null,\n      timeoutRetry: null,\n    },\n  };\n}\n\nexport function shouldRetry(\n  retryConfig: RetryConfig | null | undefined,\n  retryCount: number,\n  isTimeout: boolean,\n  loaderResponse?: LoaderResponse | undefined,\n): retryConfig is RetryConfig & boolean {\n  if (!retryConfig) {\n    return false;\n  }\n  const httpStatus = loaderResponse?.code;\n  const retry =\n    retryCount < retryConfig.maxNumRetry &&\n    (retryForHttpStatus(httpStatus) || !!isTimeout);\n  return retryConfig.shouldRetry\n    ? retryConfig.shouldRetry(\n        retryConfig,\n        retryCount,\n        isTimeout,\n        loaderResponse,\n        retry,\n      )\n    : retry;\n}\n\nexport function retryForHttpStatus(httpStatus: number | undefined) {\n  // Do not retry on status 4xx, status 0 (CORS error), or undefined (decrypt/gap/parse error)\n  return (\n    (httpStatus === 0 && navigator.onLine === false) ||\n    (!!httpStatus && (httpStatus < 400 || httpStatus > 499))\n  );\n}\n", "type BinarySearchComparison<T> = (candidate: T) => -1 | 0 | 1;\n\nconst BinarySearch = {\n  /**\n   * Searches for an item in an array which matches a certain condition.\n   * This requires the condition to only match one item in the array,\n   * and for the array to be ordered.\n   *\n   * @param list The array to search.\n   * @param comparisonFn\n   *      Called and provided a candidate item as the first argument.\n   *      Should return:\n   *          > -1 if the item should be located at a lower index than the provided item.\n   *          > 1 if the item should be located at a higher index than the provided item.\n   *          > 0 if the item is the item you're looking for.\n   *\n   * @returns the object if found, otherwise returns null\n   */\n  search: function <T>(\n    list: T[],\n    comparisonFn: BinarySearchComparison<T>,\n  ): T | null {\n    let minIndex: number = 0;\n    let maxIndex: number = list.length - 1;\n    let currentIndex: number | null = null;\n    let currentElement: T | null = null;\n\n    while (minIndex <= maxIndex) {\n      currentIndex = ((minIndex + maxIndex) / 2) | 0;\n      currentElement = list[currentIndex];\n\n      const comparisonResult = comparisonFn(currentElement);\n      if (comparisonResult > 0) {\n        minIndex = currentIndex + 1;\n      } else if (comparisonResult < 0) {\n        maxIndex = currentIndex - 1;\n      } else {\n        return currentElement;\n      }\n    }\n\n    return null;\n  },\n};\n\nexport default BinarySearch;\n", "import BinarySearch from '../utils/binary-search';\nimport { Fragment } from '../loader/fragment';\n\n/**\n * Returns first fragment whose endPdt value exceeds the given PDT, or null.\n * @param fragments - The array of candidate fragments\n * @param PDTValue - The PDT value which must be exceeded\n * @param maxFragLookUpTolerance - The amount of time that a fragment's start/end can be within in order to be considered contiguous\n */\nexport function findFragmentByPDT(\n  fragments: Array<Fragment>,\n  PDTValue: number | null,\n  maxFragLookUpTolerance: number,\n): Fragment | null {\n  if (\n    PDTValue === null ||\n    !Array.isArray(fragments) ||\n    !fragments.length ||\n    !Number.isFinite(PDTValue)\n  ) {\n    return null;\n  }\n\n  // if less than start\n  const startPDT = fragments[0].programDateTime;\n  if (PDTValue < (startPDT || 0)) {\n    return null;\n  }\n\n  const endPDT = fragments[fragments.length - 1].endProgramDateTime;\n  if (PDTValue >= (endPDT || 0)) {\n    return null;\n  }\n\n  maxFragLookUpTolerance = maxFragLookUpTolerance || 0;\n  for (let seg = 0; seg < fragments.length; ++seg) {\n    const frag = fragments[seg];\n    if (pdtWithinToleranceTest(PDTValue, maxFragLookUpTolerance, frag)) {\n      return frag;\n    }\n  }\n\n  return null;\n}\n\n/**\n * Finds a fragment based on the SN of the previous fragment; or based on the needs of the current buffer.\n * This method compensates for small buffer gaps by applying a tolerance to the start of any candidate fragment, thus\n * breaking any traps which would cause the same fragment to be continuously selected within a small range.\n * @param fragPrevious - The last frag successfully appended\n * @param fragments - The array of candidate fragments\n * @param bufferEnd - The end of the contiguous buffered range the playhead is currently within\n * @param maxFragLookUpTolerance - The amount of time that a fragment's start/end can be within in order to be considered contiguous\n * @returns a matching fragment or null\n */\nexport function findFragmentByPTS(\n  fragPrevious: Fragment | null,\n  fragments: Array<Fragment>,\n  bufferEnd: number = 0,\n  maxFragLookUpTolerance: number = 0,\n  nextFragLookupTolerance: number = 0.005,\n): Fragment | null {\n  let fragNext: Fragment | null = null;\n  if (fragPrevious) {\n    fragNext =\n      fragments[\n        (fragPrevious.sn as number) - (fragments[0].sn as number) + 1\n      ] || null;\n    // check for buffer-end rounding error\n    const bufferEdgeError = fragPrevious.endDTS - bufferEnd;\n    if (bufferEdgeError > 0 && bufferEdgeError < 0.0000015) {\n      bufferEnd += 0.0000015;\n    }\n  } else if (bufferEnd === 0 && fragments[0].start === 0) {\n    fragNext = fragments[0];\n  }\n  // Prefer the next fragment if it's within tolerance\n  if (\n    fragNext &&\n    (((!fragPrevious || fragPrevious.level === fragNext.level) &&\n      fragmentWithinToleranceTest(\n        bufferEnd,\n        maxFragLookUpTolerance,\n        fragNext,\n      ) === 0) ||\n      fragmentWithinFastStartSwitch(\n        fragNext,\n        fragPrevious,\n        Math.min(nextFragLookupTolerance, maxFragLookUpTolerance),\n      ))\n  ) {\n    return fragNext;\n  }\n  // We might be seeking past the tolerance so find the best match\n  const foundFragment = BinarySearch.search(\n    fragments,\n    fragmentWithinToleranceTest.bind(null, bufferEnd, maxFragLookUpTolerance),\n  );\n  if (foundFragment && (foundFragment !== fragPrevious || !fragNext)) {\n    return foundFragment;\n  }\n  // If no match was found return the next fragment after fragPrevious, or null\n  return fragNext;\n}\n\nfunction fragmentWithinFastStartSwitch(\n  fragNext: Fragment,\n  fragPrevious: Fragment | null,\n  nextFragLookupTolerance: number,\n): boolean {\n  if (\n    fragPrevious &&\n    fragPrevious.start === 0 &&\n    fragPrevious.level < fragNext.level &&\n    (fragPrevious.endPTS || 0) > 0\n  ) {\n    const firstDuration = fragPrevious.tagList.reduce((duration, tag) => {\n      if (tag[0] === 'INF') {\n        duration += parseFloat(tag[1]);\n      }\n      return duration;\n    }, nextFragLookupTolerance);\n    return fragNext.start <= firstDuration;\n  }\n  return false;\n}\n\n/**\n * The test function used by the findFragmentBySn's BinarySearch to look for the best match to the current buffer conditions.\n * @param candidate - The fragment to test\n * @param bufferEnd - The end of the current buffered range the playhead is currently within\n * @param maxFragLookUpTolerance - The amount of time that a fragment's start can be within in order to be considered contiguous\n * @returns 0 if it matches, 1 if too low, -1 if too high\n */\nexport function fragmentWithinToleranceTest(\n  bufferEnd = 0,\n  maxFragLookUpTolerance = 0,\n  candidate: Fragment,\n) {\n  // eagerly accept an accurate match (no tolerance)\n  if (\n    candidate.start <= bufferEnd &&\n    candidate.start + candidate.duration > bufferEnd\n  ) {\n    return 0;\n  }\n  // offset should be within fragment boundary - config.maxFragLookUpTolerance\n  // this is to cope with situations like\n  // bufferEnd = 9.991\n  // frag[\u00D8] : [0,10]\n  // frag[1] : [10,20]\n  // bufferEnd is within frag[0] range ... although what we are expecting is to return frag[1] here\n  //              frag start               frag start+duration\n  //                  |-----------------------------|\n  //              <--->                         <--->\n  //  ...--------><-----------------------------><---------....\n  // previous frag         matching fragment         next frag\n  //  return -1             return 0                 return 1\n  // logger.log(`level/sn/start/end/bufEnd:${level}/${candidate.sn}/${candidate.start}/${(candidate.start+candidate.duration)}/${bufferEnd}`);\n  // Set the lookup tolerance to be small enough to detect the current segment - ensures we don't skip over very small segments\n  const candidateLookupTolerance = Math.min(\n    maxFragLookUpTolerance,\n    candidate.duration + (candidate.deltaPTS ? candidate.deltaPTS : 0),\n  );\n  if (\n    candidate.start + candidate.duration - candidateLookupTolerance <=\n    bufferEnd\n  ) {\n    return 1;\n  } else if (\n    candidate.start - candidateLookupTolerance > bufferEnd &&\n    candidate.start\n  ) {\n    // if maxFragLookUpTolerance will have negative value then don't return -1 for first element\n    return -1;\n  }\n\n  return 0;\n}\n\n/**\n * The test function used by the findFragmentByPdt's BinarySearch to look for the best match to the current buffer conditions.\n * This function tests the candidate's program date time values, as represented in Unix time\n * @param candidate - The fragment to test\n * @param pdtBufferEnd - The Unix time representing the end of the current buffered range\n * @param maxFragLookUpTolerance - The amount of time that a fragment's start can be within in order to be considered contiguous\n * @returns true if contiguous, false otherwise\n */\nexport function pdtWithinToleranceTest(\n  pdtBufferEnd: number,\n  maxFragLookUpTolerance: number,\n  candidate: Fragment,\n): boolean {\n  const candidateLookupTolerance =\n    Math.min(\n      maxFragLookUpTolerance,\n      candidate.duration + (candidate.deltaPTS ? candidate.deltaPTS : 0),\n    ) * 1000;\n\n  // endProgramDateTime can be null, default to zero\n  const endProgramDateTime = candidate.endProgramDateTime || 0;\n  return endProgramDateTime - candidateLookupTolerance > pdtBufferEnd;\n}\n\nexport function findFragWithCC(\n  fragments: Fragment[],\n  cc: number,\n): Fragment | null {\n  return BinarySearch.search(fragments, (candidate) => {\n    if (candidate.cc < cc) {\n      return 1;\n    } else if (candidate.cc > cc) {\n      return -1;\n    } else {\n      return 0;\n    }\n  });\n}\n", "import { Events } from '../events';\nimport { ErrorDetails, ErrorTypes } from '../errors';\nimport { PlaylistContextType, PlaylistLevelType } from '../types/loader';\nimport {\n  getRetryConfig,\n  isTimeoutError,\n  shouldRetry,\n} from '../utils/error-helper';\nimport { findFragmentByPTS } from './fragment-finders';\nimport { HdcpLevel, HdcpLevels } from '../types/level';\nimport { logger } from '../utils/logger';\nimport type Hls from '../hls';\nimport type { RetryConfig } from '../config';\nimport type { NetworkComponentAPI } from '../types/component-api';\nimport type { ErrorData } from '../types/events';\nimport type { Fragment } from '../loader/fragment';\nimport type { LevelDetails } from '../loader/level-details';\n\nexport const enum NetworkErrorAction {\n  DoNothing = 0,\n  SendEndCallback = 1, // Reserved for future use\n  SendAlternateToPenaltyBox = 2,\n  RemoveAlternatePermanently = 3, // Reserved for future use\n  InsertDiscontinuity = 4, // Reserved for future use\n  RetryRequest = 5,\n}\n\nexport const enum ErrorActionFlags {\n  None = 0,\n  MoveAllAlternatesMatchingHost = 1,\n  MoveAllAlternatesMatchingHDCP = 1 << 1,\n  SwitchToSDR = 1 << 2, // Reserved for future use\n}\n\nexport type IErrorAction = {\n  action: NetworkErrorAction;\n  flags: ErrorActionFlags;\n  retryCount?: number;\n  retryConfig?: RetryConfig;\n  hdcpLevel?: HdcpLevel;\n  nextAutoLevel?: number;\n  resolved?: boolean;\n};\n\ntype PenalizedRendition = {\n  lastErrorPerfMs: number;\n  errors: ErrorData[];\n  details?: LevelDetails;\n};\n\ntype PenalizedRenditions = { [key: number]: PenalizedRendition };\n\nexport default class ErrorController implements NetworkComponentAPI {\n  private readonly hls: Hls;\n  private playlistError: number = 0;\n  private penalizedRenditions: PenalizedRenditions = {};\n  private log: (msg: any) => void;\n  private warn: (msg: any) => void;\n  private error: (msg: any) => void;\n\n  constructor(hls: Hls) {\n    this.hls = hls;\n    this.log = logger.log.bind(logger, `[info]:`);\n    this.warn = logger.warn.bind(logger, `[warning]:`);\n    this.error = logger.error.bind(logger, `[error]:`);\n    this.registerListeners();\n  }\n\n  private registerListeners() {\n    const hls = this.hls;\n    hls.on(Events.ERROR, this.onError, this);\n    hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    hls.on(Events.LEVEL_UPDATED, this.onLevelUpdated, this);\n  }\n\n  private unregisterListeners() {\n    const hls = this.hls;\n    if (!hls) {\n      return;\n    }\n    hls.off(Events.ERROR, this.onError, this);\n    hls.off(Events.ERROR, this.onErrorOut, this);\n    hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    hls.off(Events.LEVEL_UPDATED, this.onLevelUpdated, this);\n  }\n\n  destroy() {\n    this.unregisterListeners();\n    // @ts-ignore\n    this.hls = null;\n    this.penalizedRenditions = {};\n  }\n\n  startLoad(startPosition: number): void {}\n\n  stopLoad(): void {\n    this.playlistError = 0;\n  }\n\n  private getVariantLevelIndex(frag: Fragment | undefined): number {\n    return frag?.type === PlaylistLevelType.MAIN\n      ? frag.level\n      : this.hls.loadLevel;\n  }\n\n  private onManifestLoading() {\n    this.playlistError = 0;\n    this.penalizedRenditions = {};\n  }\n\n  private onLevelUpdated() {\n    this.playlistError = 0;\n  }\n\n  private onError(event: Events.ERROR, data: ErrorData) {\n    if (data.fatal) {\n      return;\n    }\n    const hls = this.hls;\n    const context = data.context;\n\n    switch (data.details) {\n      case ErrorDetails.FRAG_LOAD_ERROR:\n      case ErrorDetails.FRAG_LOAD_TIMEOUT:\n      case ErrorDetails.KEY_LOAD_ERROR:\n      case ErrorDetails.KEY_LOAD_TIMEOUT:\n        data.errorAction = this.getFragRetryOrSwitchAction(data);\n        return;\n      case ErrorDetails.FRAG_PARSING_ERROR:\n        // ignore empty segment errors marked as gap\n        if (data.frag?.gap) {\n          data.errorAction = {\n            action: NetworkErrorAction.DoNothing,\n            flags: ErrorActionFlags.None,\n          };\n          return;\n        }\n      // falls through\n      case ErrorDetails.FRAG_GAP:\n      case ErrorDetails.FRAG_DECRYPT_ERROR: {\n        // Switch level if possible, otherwise allow retry count to reach max error retries\n        data.errorAction = this.getFragRetryOrSwitchAction(data);\n        data.errorAction.action = NetworkErrorAction.SendAlternateToPenaltyBox;\n        return;\n      }\n      case ErrorDetails.LEVEL_EMPTY_ERROR:\n      case ErrorDetails.LEVEL_PARSING_ERROR:\n        {\n          // Only retry when empty and live\n          const levelIndex =\n            data.parent === PlaylistLevelType.MAIN\n              ? (data.level as number)\n              : hls.loadLevel;\n          if (\n            data.details === ErrorDetails.LEVEL_EMPTY_ERROR &&\n            !!data.context?.levelDetails?.live\n          ) {\n            data.errorAction = this.getPlaylistRetryOrSwitchAction(\n              data,\n              levelIndex,\n            );\n          } else {\n            // Escalate to fatal if not retrying or switching\n            data.levelRetry = false;\n            data.errorAction = this.getLevelSwitchAction(data, levelIndex);\n          }\n        }\n        return;\n      case ErrorDetails.LEVEL_LOAD_ERROR:\n      case ErrorDetails.LEVEL_LOAD_TIMEOUT:\n        if (typeof context?.level === 'number') {\n          data.errorAction = this.getPlaylistRetryOrSwitchAction(\n            data,\n            context.level,\n          );\n        }\n        return;\n      case ErrorDetails.AUDIO_TRACK_LOAD_ERROR:\n      case ErrorDetails.AUDIO_TRACK_LOAD_TIMEOUT:\n      case ErrorDetails.SUBTITLE_LOAD_ERROR:\n      case ErrorDetails.SUBTITLE_TRACK_LOAD_TIMEOUT:\n        if (context) {\n          const level = hls.levels[hls.loadLevel];\n          if (\n            level &&\n            ((context.type === PlaylistContextType.AUDIO_TRACK &&\n              level.hasAudioGroup(context.groupId)) ||\n              (context.type === PlaylistContextType.SUBTITLE_TRACK &&\n                level.hasSubtitleGroup(context.groupId)))\n          ) {\n            // Perform Pathway switch or Redundant failover if possible for fastest recovery\n            // otherwise allow playlist retry count to reach max error retries\n            data.errorAction = this.getPlaylistRetryOrSwitchAction(\n              data,\n              hls.loadLevel,\n            );\n            data.errorAction.action =\n              NetworkErrorAction.SendAlternateToPenaltyBox;\n            data.errorAction.flags =\n              ErrorActionFlags.MoveAllAlternatesMatchingHost;\n            return;\n          }\n        }\n        return;\n      case ErrorDetails.KEY_SYSTEM_STATUS_OUTPUT_RESTRICTED:\n        {\n          const level = hls.levels[hls.loadLevel];\n          const restrictedHdcpLevel = level?.attrs['HDCP-LEVEL'];\n          if (restrictedHdcpLevel) {\n            data.errorAction = {\n              action: NetworkErrorAction.SendAlternateToPenaltyBox,\n              flags: ErrorActionFlags.MoveAllAlternatesMatchingHDCP,\n              hdcpLevel: restrictedHdcpLevel,\n            };\n          } else {\n            this.keySystemError(data);\n          }\n        }\n        return;\n      case ErrorDetails.BUFFER_ADD_CODEC_ERROR:\n      case ErrorDetails.REMUX_ALLOC_ERROR:\n      case ErrorDetails.BUFFER_APPEND_ERROR:\n        data.errorAction = this.getLevelSwitchAction(\n          data,\n          data.level ?? hls.loadLevel,\n        );\n        return;\n      case ErrorDetails.INTERNAL_EXCEPTION:\n      case ErrorDetails.BUFFER_APPENDING_ERROR:\n      case ErrorDetails.BUFFER_FULL_ERROR:\n      case ErrorDetails.LEVEL_SWITCH_ERROR:\n      case ErrorDetails.BUFFER_STALLED_ERROR:\n      case ErrorDetails.BUFFER_SEEK_OVER_HOLE:\n      case ErrorDetails.BUFFER_NUDGE_ON_STALL:\n        data.errorAction = {\n          action: NetworkErrorAction.DoNothing,\n          flags: ErrorActionFlags.None,\n        };\n        return;\n    }\n\n    if (data.type === ErrorTypes.KEY_SYSTEM_ERROR) {\n      this.keySystemError(data);\n    }\n  }\n\n  private keySystemError(data: ErrorData) {\n    const levelIndex = this.getVariantLevelIndex(data.frag);\n    // Do not retry level. Escalate to fatal if switching levels fails.\n    data.levelRetry = false;\n    data.errorAction = this.getLevelSwitchAction(data, levelIndex);\n  }\n\n  private getPlaylistRetryOrSwitchAction(\n    data: ErrorData,\n    levelIndex: number | null | undefined,\n  ): IErrorAction {\n    const hls = this.hls;\n    const retryConfig = getRetryConfig(hls.config.playlistLoadPolicy, data);\n    const retryCount = this.playlistError++;\n    const retry = shouldRetry(\n      retryConfig,\n      retryCount,\n      isTimeoutError(data),\n      data.response,\n    );\n    if (retry) {\n      return {\n        action: NetworkErrorAction.RetryRequest,\n        flags: ErrorActionFlags.None,\n        retryConfig,\n        retryCount,\n      };\n    }\n    const errorAction = this.getLevelSwitchAction(data, levelIndex);\n    if (retryConfig) {\n      errorAction.retryConfig = retryConfig;\n      errorAction.retryCount = retryCount;\n    }\n    return errorAction;\n  }\n\n  private getFragRetryOrSwitchAction(data: ErrorData): IErrorAction {\n    const hls = this.hls;\n    // Share fragment error count accross media options (main, audio, subs)\n    // This allows for level based rendition switching when media option assets fail\n    const variantLevelIndex = this.getVariantLevelIndex(data.frag);\n    const level = hls.levels[variantLevelIndex];\n    const { fragLoadPolicy, keyLoadPolicy } = hls.config;\n    const retryConfig = getRetryConfig(\n      data.details.startsWith('key') ? keyLoadPolicy : fragLoadPolicy,\n      data,\n    );\n    const fragmentErrors = hls.levels.reduce(\n      (acc, level) => acc + level.fragmentError,\n      0,\n    );\n    // Switch levels when out of retried or level index out of bounds\n    if (level) {\n      if (data.details !== ErrorDetails.FRAG_GAP) {\n        level.fragmentError++;\n      }\n      const retry = shouldRetry(\n        retryConfig,\n        fragmentErrors,\n        isTimeoutError(data),\n        data.response,\n      );\n      if (retry) {\n        return {\n          action: NetworkErrorAction.RetryRequest,\n          flags: ErrorActionFlags.None,\n          retryConfig,\n          retryCount: fragmentErrors,\n        };\n      }\n    }\n    // Reach max retry count, or Missing level reference\n    // Switch to valid index\n    const errorAction = this.getLevelSwitchAction(data, variantLevelIndex);\n    // Add retry details to allow skipping of FRAG_PARSING_ERROR\n    if (retryConfig) {\n      errorAction.retryConfig = retryConfig;\n      errorAction.retryCount = fragmentErrors;\n    }\n    return errorAction;\n  }\n\n  private getLevelSwitchAction(\n    data: ErrorData,\n    levelIndex: number | null | undefined,\n  ): IErrorAction {\n    const hls = this.hls;\n    if (levelIndex === null || levelIndex === undefined) {\n      levelIndex = hls.loadLevel;\n    }\n    const level = this.hls.levels[levelIndex];\n    if (level) {\n      const errorDetails = data.details;\n      level.loadError++;\n      if (errorDetails === ErrorDetails.BUFFER_APPEND_ERROR) {\n        level.fragmentError++;\n      }\n      // Search for next level to retry\n      let nextLevel = -1;\n      const { levels, loadLevel, minAutoLevel, maxAutoLevel } = hls;\n      if (!hls.autoLevelEnabled) {\n        hls.loadLevel = -1;\n      }\n      const fragErrorType = data.frag?.type;\n      // Find alternate audio codec if available on audio codec error\n      const isAudioCodecError =\n        (fragErrorType === PlaylistLevelType.AUDIO &&\n          errorDetails === ErrorDetails.FRAG_PARSING_ERROR) ||\n        (data.sourceBufferName === 'audio' &&\n          (errorDetails === ErrorDetails.BUFFER_ADD_CODEC_ERROR ||\n            errorDetails === ErrorDetails.BUFFER_APPEND_ERROR));\n      const findAudioCodecAlternate =\n        isAudioCodecError &&\n        levels.some(({ audioCodec }) => level.audioCodec !== audioCodec);\n      // Find alternate video codec if available on video codec error\n      const isVideoCodecError =\n        data.sourceBufferName === 'video' &&\n        (errorDetails === ErrorDetails.BUFFER_ADD_CODEC_ERROR ||\n          errorDetails === ErrorDetails.BUFFER_APPEND_ERROR);\n      const findVideoCodecAlternate =\n        isVideoCodecError &&\n        levels.some(\n          ({ codecSet, audioCodec }) =>\n            level.codecSet !== codecSet && level.audioCodec === audioCodec,\n        );\n      const { type: playlistErrorType, groupId: playlistErrorGroupId } =\n        data.context ?? {};\n      for (let i = levels.length; i--; ) {\n        const candidate = (i + loadLevel) % levels.length;\n        if (\n          candidate !== loadLevel &&\n          candidate >= minAutoLevel &&\n          candidate <= maxAutoLevel &&\n          levels[candidate].loadError === 0\n        ) {\n          const levelCandidate = levels[candidate];\n          // Skip level switch if GAP tag is found in next level at same position\n          if (\n            errorDetails === ErrorDetails.FRAG_GAP &&\n            fragErrorType === PlaylistLevelType.MAIN &&\n            data.frag\n          ) {\n            const levelDetails = levels[candidate].details;\n            if (levelDetails) {\n              const fragCandidate = findFragmentByPTS(\n                data.frag,\n                levelDetails.fragments,\n                data.frag.start,\n              );\n              if (fragCandidate?.gap) {\n                continue;\n              }\n            }\n          } else if (\n            (playlistErrorType === PlaylistContextType.AUDIO_TRACK &&\n              levelCandidate.hasAudioGroup(playlistErrorGroupId)) ||\n            (playlistErrorType === PlaylistContextType.SUBTITLE_TRACK &&\n              levelCandidate.hasSubtitleGroup(playlistErrorGroupId))\n          ) {\n            // For audio/subs playlist errors find another group ID or fallthrough to redundant fail-over\n            continue;\n          } else if (\n            (fragErrorType === PlaylistLevelType.AUDIO &&\n              level.audioGroups?.some((groupId) =>\n                levelCandidate.hasAudioGroup(groupId),\n              )) ||\n            (fragErrorType === PlaylistLevelType.SUBTITLE &&\n              level.subtitleGroups?.some((groupId) =>\n                levelCandidate.hasSubtitleGroup(groupId),\n              )) ||\n            (findAudioCodecAlternate &&\n              level.audioCodec === levelCandidate.audioCodec) ||\n            (!findAudioCodecAlternate &&\n              level.audioCodec !== levelCandidate.audioCodec) ||\n            (findVideoCodecAlternate &&\n              level.codecSet === levelCandidate.codecSet)\n          ) {\n            // For video/audio/subs frag errors find another group ID or fallthrough to redundant fail-over\n            continue;\n          }\n          nextLevel = candidate;\n          break;\n        }\n      }\n      if (nextLevel > -1 && hls.loadLevel !== nextLevel) {\n        data.levelRetry = true;\n        this.playlistError = 0;\n        return {\n          action: NetworkErrorAction.SendAlternateToPenaltyBox,\n          flags: ErrorActionFlags.None,\n          nextAutoLevel: nextLevel,\n        };\n      }\n    }\n    // No levels to switch / Manual level selection / Level not found\n    // Resolve with Pathway switch, Redundant fail-over, or stay on lowest Level\n    return {\n      action: NetworkErrorAction.SendAlternateToPenaltyBox,\n      flags: ErrorActionFlags.MoveAllAlternatesMatchingHost,\n    };\n  }\n\n  public onErrorOut(event: Events.ERROR, data: ErrorData) {\n    switch (data.errorAction?.action) {\n      case NetworkErrorAction.DoNothing:\n        break;\n      case NetworkErrorAction.SendAlternateToPenaltyBox:\n        this.sendAlternateToPenaltyBox(data);\n        if (\n          !data.errorAction.resolved &&\n          data.details !== ErrorDetails.FRAG_GAP\n        ) {\n          data.fatal = true;\n        } else if (/MediaSource readyState: ended/.test(data.error.message)) {\n          this.warn(\n            `MediaSource ended after \"${data.sourceBufferName}\" sourceBuffer append error. Attempting to recover from media error.`,\n          );\n          this.hls.recoverMediaError();\n        }\n        break;\n      case NetworkErrorAction.RetryRequest:\n        // handled by stream and playlist/level controllers\n        break;\n    }\n\n    if (data.fatal) {\n      this.hls.stopLoad();\n      return;\n    }\n  }\n\n  private sendAlternateToPenaltyBox(data: ErrorData) {\n    const hls = this.hls;\n    const errorAction = data.errorAction;\n    if (!errorAction) {\n      return;\n    }\n    const { flags, hdcpLevel, nextAutoLevel } = errorAction;\n\n    switch (flags) {\n      case ErrorActionFlags.None:\n        this.switchLevel(data, nextAutoLevel);\n        break;\n      case ErrorActionFlags.MoveAllAlternatesMatchingHDCP:\n        if (hdcpLevel) {\n          hls.maxHdcpLevel = HdcpLevels[HdcpLevels.indexOf(hdcpLevel) - 1];\n          errorAction.resolved = true;\n        }\n        this.warn(\n          `Restricting playback to HDCP-LEVEL of \"${hls.maxHdcpLevel}\" or lower`,\n        );\n        break;\n    }\n    // If not resolved by previous actions try to switch to next level\n    if (!errorAction.resolved) {\n      this.switchLevel(data, nextAutoLevel);\n    }\n  }\n\n  private switchLevel(data: ErrorData, levelIndex: number | undefined) {\n    if (levelIndex !== undefined && data.errorAction) {\n      this.warn(`switching to level ${levelIndex} after ${data.details}`);\n      this.hls.nextAutoLevel = levelIndex;\n      data.errorAction.resolved = true;\n      // Stream controller is responsible for this but won't switch on false start\n      this.hls.nextLoadLevel = this.hls.nextAutoLevel;\n    }\n  }\n}\n", "import type Hls from '../hls';\nimport type { NetworkComponentAPI } from '../types/component-api';\nimport { getSkipValue, HlsSkip, HlsUrlParameters, Level } from '../types/level';\nimport { computeReloadInterval, mergeDetails } from '../utils/level-helper';\nimport { ErrorData } from '../types/events';\nimport { getRetryDelay, isTimeoutError } from '../utils/error-helper';\nimport { NetworkErrorAction } from './error-controller';\nimport { logger } from '../utils/logger';\nimport type { LevelDetails } from '../loader/level-details';\nimport type { MediaPlaylist } from '../types/media-playlist';\nimport type {\n  AudioTrackLoadedData,\n  LevelLoadedData,\n  TrackLoadedData,\n} from '../types/events';\n\nexport default class BasePlaylistController implements NetworkComponentAPI {\n  protected hls: Hls;\n  protected timer: number = -1;\n  protected requestScheduled: number = -1;\n  protected canLoad: boolean = false;\n  protected log: (msg: any) => void;\n  protected warn: (msg: any) => void;\n\n  constructor(hls: Hls, logPrefix: string) {\n    this.log = logger.log.bind(logger, `${logPrefix}:`);\n    this.warn = logger.warn.bind(logger, `${logPrefix}:`);\n    this.hls = hls;\n  }\n\n  public destroy(): void {\n    this.clearTimer();\n    // @ts-ignore\n    this.hls = this.log = this.warn = null;\n  }\n\n  protected clearTimer(): void {\n    if (this.timer !== -1) {\n      self.clearTimeout(this.timer);\n      this.timer = -1;\n    }\n  }\n\n  public startLoad(): void {\n    this.canLoad = true;\n    this.requestScheduled = -1;\n    this.loadPlaylist();\n  }\n\n  public stopLoad(): void {\n    this.canLoad = false;\n    this.clearTimer();\n  }\n\n  protected switchParams(\n    playlistUri: string,\n    previous: LevelDetails | undefined,\n    current: LevelDetails | undefined,\n  ): HlsUrlParameters | undefined {\n    const renditionReports = previous?.renditionReports;\n    if (renditionReports) {\n      let foundIndex = -1;\n      for (let i = 0; i < renditionReports.length; i++) {\n        const attr = renditionReports[i];\n        let uri: string;\n        try {\n          uri = new self.URL(attr.URI, previous.url).href;\n        } catch (error) {\n          logger.warn(\n            `Could not construct new URL for Rendition Report: ${error}`,\n          );\n          uri = attr.URI || '';\n        }\n        // Use exact match. Otherwise, the last partial match, if any, will be used\n        // (Playlist URI includes a query string that the Rendition Report does not)\n        if (uri === playlistUri) {\n          foundIndex = i;\n          break;\n        } else if (uri === playlistUri.substring(0, uri.length)) {\n          foundIndex = i;\n        }\n      }\n      if (foundIndex !== -1) {\n        const attr = renditionReports[foundIndex];\n        const msn = parseInt(attr['LAST-MSN']) || previous?.lastPartSn;\n        let part = parseInt(attr['LAST-PART']) || previous?.lastPartIndex;\n        if (this.hls.config.lowLatencyMode) {\n          const currentGoal = Math.min(\n            previous.age - previous.partTarget,\n            previous.targetduration,\n          );\n          if (part >= 0 && currentGoal > previous.partTarget) {\n            part += 1;\n          }\n        }\n        const skip = current && getSkipValue(current);\n        return new HlsUrlParameters(msn, part >= 0 ? part : undefined, skip);\n      }\n    }\n  }\n\n  protected loadPlaylist(hlsUrlParameters?: HlsUrlParameters): void {\n    if (this.requestScheduled === -1) {\n      this.requestScheduled = self.performance.now();\n    }\n    // Loading is handled by the subclasses\n  }\n\n  protected shouldLoadPlaylist(\n    playlist: Level | MediaPlaylist | null | undefined,\n  ): boolean {\n    return (\n      this.canLoad &&\n      !!playlist &&\n      !!playlist.url &&\n      (!playlist.details || playlist.details.live)\n    );\n  }\n\n  protected shouldReloadPlaylist(\n    playlist: Level | MediaPlaylist | null | undefined,\n  ): boolean {\n    return (\n      this.timer === -1 &&\n      this.requestScheduled === -1 &&\n      this.shouldLoadPlaylist(playlist)\n    );\n  }\n\n  protected playlistLoaded(\n    index: number,\n    data: LevelLoadedData | AudioTrackLoadedData | TrackLoadedData,\n    previousDetails?: LevelDetails,\n  ) {\n    const { details, stats } = data;\n\n    // Set last updated date-time\n    const now = self.performance.now();\n    const elapsed = stats.loading.first\n      ? Math.max(0, now - stats.loading.first)\n      : 0;\n    details.advancedDateTime = Date.now() - elapsed;\n\n    // if current playlist is a live playlist, arm a timer to reload it\n    if (details.live || previousDetails?.live) {\n      details.reloaded(previousDetails);\n      if (previousDetails) {\n        this.log(\n          `live playlist ${index} ${\n            details.advanced\n              ? 'REFRESHED ' + details.lastPartSn + '-' + details.lastPartIndex\n              : details.updated\n                ? 'UPDATED'\n                : 'MISSED'\n          }`,\n        );\n      }\n      // Merge live playlists to adjust fragment starts and fill in delta playlist skipped segments\n      if (previousDetails && details.fragments.length > 0) {\n        mergeDetails(previousDetails, details);\n      }\n      if (!this.canLoad || !details.live) {\n        return;\n      }\n      let deliveryDirectives: HlsUrlParameters | undefined;\n      let msn: number | undefined = undefined;\n      let part: number | undefined = undefined;\n      if (details.canBlockReload && details.endSN && details.advanced) {\n        // Load level with LL-HLS delivery directives\n        const lowLatencyMode = this.hls.config.lowLatencyMode;\n        const lastPartSn = details.lastPartSn;\n        const endSn = details.endSN;\n        const lastPartIndex = details.lastPartIndex;\n        const hasParts = lastPartIndex !== -1;\n        const lastPart = lastPartSn === endSn;\n        // When low latency mode is disabled, we'll skip part requests once the last part index is found\n        const nextSnStartIndex = lowLatencyMode ? 0 : lastPartIndex;\n        if (hasParts) {\n          msn = lastPart ? endSn + 1 : lastPartSn;\n          part = lastPart ? nextSnStartIndex : lastPartIndex + 1;\n        } else {\n          msn = endSn + 1;\n        }\n        // Low-Latency CDN Tune-in: \"age\" header and time since load indicates we're behind by more than one part\n        // Update directives to obtain the Playlist that has the estimated additional duration of media\n        const lastAdvanced = details.age;\n        const cdnAge = lastAdvanced + details.ageHeader;\n        let currentGoal = Math.min(\n          cdnAge - details.partTarget,\n          details.targetduration * 1.5,\n        );\n        if (currentGoal > 0) {\n          if (previousDetails && currentGoal > previousDetails.tuneInGoal) {\n            // If we attempted to get the next or latest playlist update, but currentGoal increased,\n            // then we either can't catchup, or the \"age\" header cannot be trusted.\n            this.warn(\n              `CDN Tune-in goal increased from: ${previousDetails.tuneInGoal} to: ${currentGoal} with playlist age: ${details.age}`,\n            );\n            currentGoal = 0;\n          } else {\n            const segments = Math.floor(currentGoal / details.targetduration);\n            msn += segments;\n            if (part !== undefined) {\n              const parts = Math.round(\n                (currentGoal % details.targetduration) / details.partTarget,\n              );\n              part += parts;\n            }\n            this.log(\n              `CDN Tune-in age: ${\n                details.ageHeader\n              }s last advanced ${lastAdvanced.toFixed(\n                2,\n              )}s goal: ${currentGoal} skip sn ${segments} to part ${part}`,\n            );\n          }\n          details.tuneInGoal = currentGoal;\n        }\n        deliveryDirectives = this.getDeliveryDirectives(\n          details,\n          data.deliveryDirectives,\n          msn,\n          part,\n        );\n        if (lowLatencyMode || !lastPart) {\n          this.loadPlaylist(deliveryDirectives);\n          return;\n        }\n      } else if (details.canBlockReload || details.canSkipUntil) {\n        deliveryDirectives = this.getDeliveryDirectives(\n          details,\n          data.deliveryDirectives,\n          msn,\n          part,\n        );\n      }\n      const bufferInfo = this.hls.mainForwardBufferInfo;\n      const position = bufferInfo ? bufferInfo.end - bufferInfo.len : 0;\n      const distanceToLiveEdgeMs = (details.edge - position) * 1000;\n      const reloadInterval = computeReloadInterval(\n        details,\n        distanceToLiveEdgeMs,\n      );\n      if (details.updated && now > this.requestScheduled + reloadInterval) {\n        this.requestScheduled = stats.loading.start;\n      }\n\n      if (msn !== undefined && details.canBlockReload) {\n        this.requestScheduled =\n          stats.loading.first +\n          reloadInterval -\n          (details.partTarget * 1000 || 1000);\n      } else if (\n        this.requestScheduled === -1 ||\n        this.requestScheduled + reloadInterval < now\n      ) {\n        this.requestScheduled = now;\n      } else if (this.requestScheduled - now <= 0) {\n        this.requestScheduled += reloadInterval;\n      }\n      let estimatedTimeUntilUpdate = this.requestScheduled - now;\n      estimatedTimeUntilUpdate = Math.max(0, estimatedTimeUntilUpdate);\n      this.log(\n        `reload live playlist ${index} in ${Math.round(\n          estimatedTimeUntilUpdate,\n        )} ms`,\n      );\n      // this.log(\n      //   `live reload ${details.updated ? 'REFRESHED' : 'MISSED'}\n      // reload in ${estimatedTimeUntilUpdate / 1000}\n      // round trip ${(stats.loading.end - stats.loading.start) / 1000}\n      // diff ${\n      //   (reloadInterval -\n      //     (estimatedTimeUntilUpdate +\n      //       stats.loading.end -\n      //       stats.loading.start)) /\n      //   1000\n      // }\n      // reload interval ${reloadInterval / 1000}\n      // target duration ${details.targetduration}\n      // distance to edge ${distanceToLiveEdgeMs / 1000}`\n      // );\n\n      this.timer = self.setTimeout(\n        () => this.loadPlaylist(deliveryDirectives),\n        estimatedTimeUntilUpdate,\n      );\n    } else {\n      this.clearTimer();\n    }\n  }\n\n  private getDeliveryDirectives(\n    details: LevelDetails,\n    previousDeliveryDirectives: HlsUrlParameters | null,\n    msn?: number,\n    part?: number,\n  ): HlsUrlParameters {\n    let skip = getSkipValue(details);\n    if (previousDeliveryDirectives?.skip && details.deltaUpdateFailed) {\n      msn = previousDeliveryDirectives.msn;\n      part = previousDeliveryDirectives.part;\n      skip = HlsSkip.No;\n    }\n    return new HlsUrlParameters(msn, part, skip);\n  }\n\n  protected checkRetry(errorEvent: ErrorData): boolean {\n    const errorDetails = errorEvent.details;\n    const isTimeout = isTimeoutError(errorEvent);\n    const errorAction = errorEvent.errorAction;\n    const { action, retryCount = 0, retryConfig } = errorAction || {};\n    const retry =\n      !!errorAction &&\n      !!retryConfig &&\n      (action === NetworkErrorAction.RetryRequest ||\n        (!errorAction.resolved &&\n          action === NetworkErrorAction.SendAlternateToPenaltyBox));\n    if (retry) {\n      this.requestScheduled = -1;\n      if (retryCount >= retryConfig.maxNumRetry) {\n        return false;\n      }\n      if (isTimeout && errorEvent.context?.deliveryDirectives) {\n        // The LL-HLS request already timed out so retry immediately\n        this.warn(\n          `Retrying playlist loading ${retryCount + 1}/${\n            retryConfig.maxNumRetry\n          } after \"${errorDetails}\" without delivery-directives`,\n        );\n        this.loadPlaylist();\n      } else {\n        const delay = getRetryDelay(retryConfig, retryCount);\n        // Schedule level/track reload\n        this.timer = self.setTimeout(() => this.loadPlaylist(), delay);\n        this.warn(\n          `Retrying playlist loading ${retryCount + 1}/${\n            retryConfig.maxNumRetry\n          } after \"${errorDetails}\" in ${delay}ms`,\n        );\n      }\n      // `levelRetry = true` used to inform other controllers that a retry is happening\n      errorEvent.levelRetry = true;\n      errorAction.resolved = true;\n    }\n    return retry;\n  }\n}\n", "/*\n * compute an Exponential Weighted moving average\n * - https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average\n *  - heavily inspired from shaka-player\n */\n\nclass EWMA {\n  public readonly halfLife: number;\n  private alpha_: number;\n  private estimate_: number;\n  private totalWeight_: number;\n\n  //  About half of the estimated value will be from the last |halfLife| samples by weight.\n  constructor(halfLife: number, estimate: number = 0, weight: number = 0) {\n    this.halfLife = halfLife;\n    // Larger values of alpha expire historical data more slowly.\n    this.alpha_ = halfLife ? Math.exp(Math.log(0.5) / halfLife) : 0;\n    this.estimate_ = estimate;\n    this.totalWeight_ = weight;\n  }\n\n  sample(weight: number, value: number) {\n    const adjAlpha = Math.pow(this.alpha_, weight);\n    this.estimate_ = value * (1 - adjAlpha) + adjAlpha * this.estimate_;\n    this.totalWeight_ += weight;\n  }\n\n  getTotalWeight(): number {\n    return this.totalWeight_;\n  }\n\n  getEstimate(): number {\n    if (this.alpha_) {\n      const zeroFactor = 1 - Math.pow(this.alpha_, this.totalWeight_);\n      if (zeroFactor) {\n        return this.estimate_ / zeroFactor;\n      }\n    }\n    return this.estimate_;\n  }\n}\n\nexport default EWMA;\n", "/*\n * EWMA Bandwidth Estimator\n *  - heavily inspired from shaka-player\n * Tracks bandwidth samples and estimates available bandwidth.\n * Based on the minimum of two exponentially-weighted moving averages with\n * different half-lives.\n */\n\nimport EWMA from '../utils/ewma';\n\nclass EwmaBandWidthEstimator {\n  private defaultEstimate_: number;\n  private minWeight_: number;\n  private minDelayMs_: number;\n  private slow_: EWMA;\n  private fast_: EWMA;\n  private defaultTTFB_: number;\n  private ttfb_: EWMA;\n\n  constructor(\n    slow: number,\n    fast: number,\n    defaultEstimate: number,\n    defaultTTFB: number = 100,\n  ) {\n    this.defaultEstimate_ = defaultEstimate;\n    this.minWeight_ = 0.001;\n    this.minDelayMs_ = 50;\n    this.slow_ = new EWMA(slow);\n    this.fast_ = new EWMA(fast);\n    this.defaultTTFB_ = defaultTTFB;\n    this.ttfb_ = new EWMA(slow);\n  }\n\n  update(slow: number, fast: number) {\n    const { slow_, fast_, ttfb_ } = this;\n    if (slow_.halfLife !== slow) {\n      this.slow_ = new EWMA(slow, slow_.getEstimate(), slow_.getTotalWeight());\n    }\n    if (fast_.halfLife !== fast) {\n      this.fast_ = new EWMA(fast, fast_.getEstimate(), fast_.getTotalWeight());\n    }\n    if (ttfb_.halfLife !== slow) {\n      this.ttfb_ = new EWMA(slow, ttfb_.getEstimate(), ttfb_.getTotalWeight());\n    }\n  }\n\n  sample(durationMs: number, numBytes: number) {\n    durationMs = Math.max(durationMs, this.minDelayMs_);\n    const numBits = 8 * numBytes;\n    // weight is duration in seconds\n    const durationS = durationMs / 1000;\n    // value is bandwidth in bits/s\n    const bandwidthInBps = numBits / durationS;\n    this.fast_.sample(durationS, bandwidthInBps);\n    this.slow_.sample(durationS, bandwidthInBps);\n  }\n\n  sampleTTFB(ttfb: number) {\n    // weight is frequency curve applied to TTFB in seconds\n    // (longer times have less weight with expected input under 1 second)\n    const seconds = ttfb / 1000;\n    const weight = Math.sqrt(2) * Math.exp(-Math.pow(seconds, 2) / 2);\n    this.ttfb_.sample(weight, Math.max(ttfb, 5));\n  }\n\n  canEstimate(): boolean {\n    return this.fast_.getTotalWeight() >= this.minWeight_;\n  }\n\n  getEstimate(): number {\n    if (this.canEstimate()) {\n      // console.log('slow estimate:'+ Math.round(this.slow_.getEstimate()));\n      // console.log('fast estimate:'+ Math.round(this.fast_.getEstimate()));\n      // Take the minimum of these two estimates.  This should have the effect of\n      // adapting down quickly, but up more slowly.\n      return Math.min(this.fast_.getEstimate(), this.slow_.getEstimate());\n    } else {\n      return this.defaultEstimate_;\n    }\n  }\n\n  getEstimateTTFB(): number {\n    if (this.ttfb_.getTotalWeight() >= this.minWeight_) {\n      return this.ttfb_.getEstimate();\n    } else {\n      return this.defaultTTFB_;\n    }\n  }\n\n  destroy() {}\n}\nexport default EwmaBandWidthEstimator;\n", "import { mimeTypeForCodec } from './codecs';\nimport type { Level, VideoRange } from '../types/level';\nimport type { AudioSelectionOption } from '../types/media-playlist';\nimport type { AudioTracksByGroup } from './rendition-helper';\n\nexport type MediaDecodingInfo = {\n  supported: boolean;\n  configurations: readonly MediaDecodingConfiguration[];\n  decodingInfoResults: readonly MediaCapabilitiesDecodingInfo[];\n  error?: Error;\n};\n\ntype BaseVideoConfiguration = Omit<VideoConfiguration, 'contentType'>;\n\nexport const SUPPORTED_INFO_DEFAULT: MediaDecodingInfo = {\n  supported: true,\n  configurations: [] as MediaDecodingConfiguration[],\n  decodingInfoResults: [\n    {\n      supported: true,\n      powerEfficient: true,\n      smooth: true,\n    },\n  ],\n} as const;\n\nexport const SUPPORTED_INFO_CACHE: Record<\n  string,\n  Promise<MediaCapabilitiesDecodingInfo>\n> = {};\n\nexport function requiresMediaCapabilitiesDecodingInfo(\n  level: Level,\n  audioTracksByGroup: AudioTracksByGroup,\n  currentVideoRange: VideoRange | undefined,\n  currentFrameRate: number,\n  currentBw: number,\n  audioPreference: AudioSelectionOption | undefined,\n): boolean {\n  // Only test support when configuration is exceeds minimum options\n  const audioGroups = level.audioCodec ? level.audioGroups : null;\n  const audioCodecPreference = audioPreference?.audioCodec;\n  const channelsPreference = audioPreference?.channels;\n  const maxChannels = channelsPreference\n    ? parseInt(channelsPreference)\n    : audioCodecPreference\n      ? Infinity\n      : 2;\n  let audioChannels: Record<string, number> | null = null;\n  if (audioGroups?.length) {\n    try {\n      if (audioGroups.length === 1 && audioGroups[0]) {\n        audioChannels = audioTracksByGroup.groups[audioGroups[0]].channels;\n      } else {\n        audioChannels = audioGroups.reduce(\n          (acc, groupId) => {\n            if (groupId) {\n              const audioTrackGroup = audioTracksByGroup.groups[groupId];\n              if (!audioTrackGroup) {\n                throw new Error(`Audio track group ${groupId} not found`);\n              }\n              // Sum all channel key values\n              Object.keys(audioTrackGroup.channels).forEach((key) => {\n                acc[key] = (acc[key] || 0) + audioTrackGroup.channels[key];\n              });\n            }\n            return acc;\n          },\n          { 2: 0 },\n        );\n      }\n    } catch (error) {\n      return true;\n    }\n  }\n  return (\n    (level.videoCodec !== undefined &&\n      ((level.width > 1920 && level.height > 1088) ||\n        (level.height > 1920 && level.width > 1088) ||\n        level.frameRate > Math.max(currentFrameRate, 30) ||\n        (level.videoRange !== 'SDR' &&\n          level.videoRange !== currentVideoRange) ||\n        level.bitrate > Math.max(currentBw, 8e6))) ||\n    (!!audioChannels &&\n      Number.isFinite(maxChannels) &&\n      Object.keys(audioChannels).some(\n        (channels) => parseInt(channels) > maxChannels,\n      ))\n  );\n}\n\nexport function getMediaDecodingInfoPromise(\n  level: Level,\n  audioTracksByGroup: AudioTracksByGroup,\n  mediaCapabilities: MediaCapabilities | undefined,\n): Promise<MediaDecodingInfo> {\n  const videoCodecs = level.videoCodec;\n  const audioCodecs = level.audioCodec;\n  if (!videoCodecs || !audioCodecs || !mediaCapabilities) {\n    return Promise.resolve(SUPPORTED_INFO_DEFAULT);\n  }\n\n  const baseVideoConfiguration: BaseVideoConfiguration = {\n    width: level.width,\n    height: level.height,\n    bitrate: Math.ceil(Math.max(level.bitrate * 0.9, level.averageBitrate)),\n    // Assume a framerate of 30fps since MediaCapabilities will not accept Level default of 0.\n    framerate: level.frameRate || 30,\n  };\n\n  const videoRange = level.videoRange;\n  if (videoRange !== 'SDR') {\n    baseVideoConfiguration.transferFunction =\n      videoRange.toLowerCase() as TransferFunction;\n  }\n\n  const configurations: MediaDecodingConfiguration[] = videoCodecs\n    .split(',')\n    .map((videoCodec) => ({\n      type: 'media-source',\n      video: {\n        ...baseVideoConfiguration,\n        contentType: mimeTypeForCodec(videoCodec, 'video'),\n      },\n    }));\n\n  if (audioCodecs && level.audioGroups) {\n    level.audioGroups.forEach((audioGroupId) => {\n      if (!audioGroupId) {\n        return;\n      }\n      audioTracksByGroup.groups[audioGroupId]?.tracks.forEach((audioTrack) => {\n        if (audioTrack.groupId === audioGroupId) {\n          const channels = audioTrack.channels || '';\n          const channelsNumber = parseFloat(channels);\n          if (Number.isFinite(channelsNumber) && channelsNumber > 2) {\n            configurations.push.apply(\n              configurations,\n              audioCodecs.split(',').map((audioCodec) => ({\n                type: 'media-source',\n                audio: {\n                  contentType: mimeTypeForCodec(audioCodec, 'audio'),\n                  channels: '' + channelsNumber,\n                  // spatialRendering:\n                  //   audioCodec === 'ec-3' && channels.indexOf('JOC'),\n                },\n              })),\n            );\n          }\n        }\n      });\n    });\n  }\n\n  return Promise.all(\n    configurations.map((configuration) => {\n      // Cache MediaCapabilities promises\n      const decodingInfoKey = getMediaDecodingInfoKey(configuration);\n      return (\n        SUPPORTED_INFO_CACHE[decodingInfoKey] ||\n        (SUPPORTED_INFO_CACHE[decodingInfoKey] =\n          mediaCapabilities.decodingInfo(configuration))\n      );\n    }),\n  )\n    .then((decodingInfoResults) => ({\n      supported: !decodingInfoResults.some((info) => !info.supported),\n      configurations,\n      decodingInfoResults,\n    }))\n    .catch((error) => ({\n      supported: false,\n      configurations,\n      decodingInfoResults: [] as MediaCapabilitiesDecodingInfo[],\n      error,\n    }));\n}\n\nfunction getMediaDecodingInfoKey(config: MediaDecodingConfiguration): string {\n  const { audio, video } = config;\n  const mediaConfig = video || audio;\n  if (mediaConfig) {\n    const codec = mediaConfig.contentType.split('\"')[1];\n    if (video) {\n      return `r${video.height}x${video.width}f${Math.ceil(video.framerate)}${\n        video.transferFunction || 'sd'\n      }_${codec}_${Math.ceil(video.bitrate / 1e5)}`;\n    }\n    if (audio) {\n      return `c${audio.channels}${audio.spatialRendering ? 's' : 'n'}_${codec}`;\n    }\n  }\n  return '';\n}\n", "import { type VideoRange, VideoRangeValues } from '../types/level';\nimport type { VideoSelectionOption } from '../types/media-playlist';\n\n/**\n * @returns Whether we can detect and validate HDR capability within the window context\n */\nexport function isHdrSupported() {\n  if (typeof matchMedia === 'function') {\n    const mediaQueryList = matchMedia('(dynamic-range: high)');\n    const badQuery = matchMedia('bad query');\n    if (mediaQueryList.media !== badQuery.media) {\n      return mediaQueryList.matches === true;\n    }\n  }\n  return false;\n}\n\n/**\n * Sanitizes inputs to return the active video selection options for HDR/SDR.\n * When both inputs are null:\n *\n *    `{ preferHDR: false, allowedVideoRanges: [] }`\n *\n * When `currentVideoRange` non-null, maintain the active range:\n *\n *    `{ preferHDR: currentVideoRange !== 'SDR', allowedVideoRanges: [currentVideoRange] }`\n *\n * When VideoSelectionOption non-null:\n *\n *  - Allow all video ranges if `allowedVideoRanges` unspecified.\n *  - If `preferHDR` is non-null use the value to filter `allowedVideoRanges`.\n *  - Else check window for HDR support and set `preferHDR` to the result.\n *\n * @param currentVideoRange\n * @param videoPreference\n */\nexport function getVideoSelectionOptions(\n  currentVideoRange: VideoRange | undefined,\n  videoPreference: VideoSelectionOption | undefined,\n) {\n  let preferHDR = false;\n  let allowedVideoRanges: Array<VideoRange> = [];\n\n  if (currentVideoRange) {\n    preferHDR = currentVideoRange !== 'SDR';\n    allowedVideoRanges = [currentVideoRange];\n  }\n\n  if (videoPreference) {\n    allowedVideoRanges =\n      videoPreference.allowedVideoRanges || VideoRangeValues.slice(0);\n    preferHDR =\n      videoPreference.preferHDR !== undefined\n        ? videoPreference.preferHDR\n        : isHdrSupported();\n\n    if (preferHDR) {\n      allowedVideoRanges = allowedVideoRanges.filter(\n        (range: VideoRange) => range !== 'SDR',\n      );\n    } else {\n      allowedVideoRanges = ['SDR'];\n    }\n  }\n\n  return {\n    preferHDR,\n    allowedVideoRanges,\n  };\n}\n", "import { codecsSetSelectionPreferenceValue } from './codecs';\nimport { getVideoSelectionOptions } from './hdr';\nimport { logger } from './logger';\nimport type { Level, VideoRange } from '../types/level';\nimport type {\n  AudioSelectionOption,\n  MediaPlaylist,\n  SubtitleSelectionOption,\n  VideoSelectionOption,\n} from '../types/media-playlist';\n\nexport type CodecSetTier = {\n  minBitrate: number;\n  minHeight: number;\n  minFramerate: number;\n  maxScore: number;\n  videoRanges: Record<string, number>;\n  channels: Record<string, number>;\n  hasDefaultAudio: boolean;\n  fragmentError: number;\n};\n\ntype AudioTrackGroup = {\n  tracks: MediaPlaylist[];\n  channels: Record<string, number>;\n  hasDefault: boolean;\n  hasAutoSelect: boolean;\n};\ntype StartParameters = {\n  codecSet: string | undefined;\n  videoRanges: Array<VideoRange>;\n  preferHDR: boolean;\n  minFramerate: number;\n  minBitrate: number;\n};\n\nexport function getStartCodecTier(\n  codecTiers: Record<string, CodecSetTier>,\n  currentVideoRange: VideoRange | undefined,\n  currentBw: number,\n  audioPreference: AudioSelectionOption | undefined,\n  videoPreference: VideoSelectionOption | undefined,\n): StartParameters {\n  const codecSets = Object.keys(codecTiers);\n  const channelsPreference = audioPreference?.channels;\n  const audioCodecPreference = audioPreference?.audioCodec;\n  const preferStereo = channelsPreference && parseInt(channelsPreference) === 2;\n  // Use first level set to determine stereo, and minimum resolution and framerate\n  let hasStereo = true;\n  let hasCurrentVideoRange = false;\n  let minHeight = Infinity;\n  let minFramerate = Infinity;\n  let minBitrate = Infinity;\n  let selectedScore = 0;\n  let videoRanges: Array<VideoRange> = [];\n\n  const { preferHDR, allowedVideoRanges } = getVideoSelectionOptions(\n    currentVideoRange,\n    videoPreference,\n  );\n\n  for (let i = codecSets.length; i--; ) {\n    const tier = codecTiers[codecSets[i]];\n    hasStereo = tier.channels[2] > 0;\n    minHeight = Math.min(minHeight, tier.minHeight);\n    minFramerate = Math.min(minFramerate, tier.minFramerate);\n    minBitrate = Math.min(minBitrate, tier.minBitrate);\n    const matchingVideoRanges = allowedVideoRanges.filter(\n      (range) => tier.videoRanges[range] > 0,\n    );\n    if (matchingVideoRanges.length > 0) {\n      hasCurrentVideoRange = true;\n      videoRanges = matchingVideoRanges;\n    }\n  }\n  minHeight = Number.isFinite(minHeight) ? minHeight : 0;\n  minFramerate = Number.isFinite(minFramerate) ? minFramerate : 0;\n  const maxHeight = Math.max(1080, minHeight);\n  const maxFramerate = Math.max(30, minFramerate);\n  minBitrate = Number.isFinite(minBitrate) ? minBitrate : currentBw;\n  currentBw = Math.max(minBitrate, currentBw);\n  // If there are no variants with matching preference, set currentVideoRange to undefined\n  if (!hasCurrentVideoRange) {\n    currentVideoRange = undefined;\n    videoRanges = [];\n  }\n  const codecSet = codecSets.reduce(\n    (selected: string | undefined, candidate: string) => {\n      // Remove candiates which do not meet bitrate, default audio, stereo or channels preference, 1080p or lower, 30fps or lower, or SDR/HDR selection if present\n      const candidateTier = codecTiers[candidate];\n      if (candidate === selected) {\n        return selected;\n      }\n      if (candidateTier.minBitrate > currentBw) {\n        logStartCodecCandidateIgnored(\n          candidate,\n          `min bitrate of ${candidateTier.minBitrate} > current estimate of ${currentBw}`,\n        );\n        return selected;\n      }\n      if (!candidateTier.hasDefaultAudio) {\n        logStartCodecCandidateIgnored(\n          candidate,\n          `no renditions with default or auto-select sound found`,\n        );\n        return selected;\n      }\n      if (\n        audioCodecPreference &&\n        candidate.indexOf(audioCodecPreference.substring(0, 4)) % 5 !== 0\n      ) {\n        logStartCodecCandidateIgnored(\n          candidate,\n          `audio codec preference \"${audioCodecPreference}\" not found`,\n        );\n        return selected;\n      }\n      if (channelsPreference && !preferStereo) {\n        if (!candidateTier.channels[channelsPreference]) {\n          logStartCodecCandidateIgnored(\n            candidate,\n            `no renditions with ${channelsPreference} channel sound found (channels options: ${Object.keys(\n              candidateTier.channels,\n            )})`,\n          );\n          return selected;\n        }\n      } else if (\n        (!audioCodecPreference || preferStereo) &&\n        hasStereo &&\n        candidateTier.channels['2'] === 0\n      ) {\n        logStartCodecCandidateIgnored(\n          candidate,\n          `no renditions with stereo sound found`,\n        );\n        return selected;\n      }\n      if (candidateTier.minHeight > maxHeight) {\n        logStartCodecCandidateIgnored(\n          candidate,\n          `min resolution of ${candidateTier.minHeight} > maximum of ${maxHeight}`,\n        );\n        return selected;\n      }\n      if (candidateTier.minFramerate > maxFramerate) {\n        logStartCodecCandidateIgnored(\n          candidate,\n          `min framerate of ${candidateTier.minFramerate} > maximum of ${maxFramerate}`,\n        );\n        return selected;\n      }\n      if (!videoRanges.some((range) => candidateTier.videoRanges[range] > 0)) {\n        logStartCodecCandidateIgnored(\n          candidate,\n          `no variants with VIDEO-RANGE of ${JSON.stringify(\n            videoRanges,\n          )} found`,\n        );\n        return selected;\n      }\n      if (candidateTier.maxScore < selectedScore) {\n        logStartCodecCandidateIgnored(\n          candidate,\n          `max score of ${candidateTier.maxScore} < selected max of ${selectedScore}`,\n        );\n        return selected;\n      }\n      // Remove candiates with less preferred codecs or more errors\n      if (\n        selected &&\n        (codecsSetSelectionPreferenceValue(candidate) >=\n          codecsSetSelectionPreferenceValue(selected) ||\n          candidateTier.fragmentError > codecTiers[selected].fragmentError)\n      ) {\n        return selected;\n      }\n      selectedScore = candidateTier.maxScore;\n      return candidate;\n    },\n    undefined,\n  );\n  return {\n    codecSet,\n    videoRanges,\n    preferHDR,\n    minFramerate,\n    minBitrate,\n  };\n}\n\nfunction logStartCodecCandidateIgnored(codeSet: string, reason: string) {\n  logger.log(\n    `[abr] start candidates with \"${codeSet}\" ignored because ${reason}`,\n  );\n}\n\nexport type AudioTracksByGroup = {\n  hasDefaultAudio: boolean;\n  hasAutoSelectAudio: boolean;\n  groups: Record<string, AudioTrackGroup>;\n};\n\nexport function getAudioTracksByGroup(allAudioTracks: MediaPlaylist[]) {\n  return allAudioTracks.reduce(\n    (audioTracksByGroup: AudioTracksByGroup, track) => {\n      let trackGroup = audioTracksByGroup.groups[track.groupId];\n      if (!trackGroup) {\n        trackGroup = audioTracksByGroup.groups[track.groupId] = {\n          tracks: [],\n          channels: { 2: 0 },\n          hasDefault: false,\n          hasAutoSelect: false,\n        };\n      }\n      trackGroup.tracks.push(track);\n      const channelsKey = track.channels || '2';\n      trackGroup.channels[channelsKey] =\n        (trackGroup.channels[channelsKey] || 0) + 1;\n      trackGroup.hasDefault = trackGroup.hasDefault || track.default;\n      trackGroup.hasAutoSelect = trackGroup.hasAutoSelect || track.autoselect;\n      if (trackGroup.hasDefault) {\n        audioTracksByGroup.hasDefaultAudio = true;\n      }\n      if (trackGroup.hasAutoSelect) {\n        audioTracksByGroup.hasAutoSelectAudio = true;\n      }\n      return audioTracksByGroup;\n    },\n    {\n      hasDefaultAudio: false,\n      hasAutoSelectAudio: false,\n      groups: {},\n    },\n  );\n}\n\nexport function getCodecTiers(\n  levels: Level[],\n  audioTracksByGroup: AudioTracksByGroup,\n  minAutoLevel: number,\n  maxAutoLevel: number,\n): Record<string, CodecSetTier> {\n  return levels\n    .slice(minAutoLevel, maxAutoLevel + 1)\n    .reduce((tiers: Record<string, CodecSetTier>, level) => {\n      if (!level.codecSet) {\n        return tiers;\n      }\n      const audioGroups = level.audioGroups;\n      let tier = tiers[level.codecSet];\n      if (!tier) {\n        tiers[level.codecSet] = tier = {\n          minBitrate: Infinity,\n          minHeight: Infinity,\n          minFramerate: Infinity,\n          maxScore: 0,\n          videoRanges: { SDR: 0 },\n          channels: { '2': 0 },\n          hasDefaultAudio: !audioGroups,\n          fragmentError: 0,\n        };\n      }\n      tier.minBitrate = Math.min(tier.minBitrate, level.bitrate);\n      const lesserWidthOrHeight = Math.min(level.height, level.width);\n      tier.minHeight = Math.min(tier.minHeight, lesserWidthOrHeight);\n      tier.minFramerate = Math.min(tier.minFramerate, level.frameRate);\n      tier.maxScore = Math.max(tier.maxScore, level.score);\n      tier.fragmentError += level.fragmentError;\n      tier.videoRanges[level.videoRange] =\n        (tier.videoRanges[level.videoRange] || 0) + 1;\n      if (__USE_ALT_AUDIO__ && audioGroups) {\n        audioGroups.forEach((audioGroupId) => {\n          if (!audioGroupId) {\n            return;\n          }\n          const audioGroup = audioTracksByGroup.groups[audioGroupId];\n          if (!audioGroup) {\n            return;\n          }\n          // Default audio is any group with DEFAULT=YES, or if missing then any group with AUTOSELECT=YES, or all variants\n          tier.hasDefaultAudio =\n            tier.hasDefaultAudio || audioTracksByGroup.hasDefaultAudio\n              ? audioGroup.hasDefault\n              : audioGroup.hasAutoSelect ||\n                (!audioTracksByGroup.hasDefaultAudio &&\n                  !audioTracksByGroup.hasAutoSelectAudio);\n          Object.keys(audioGroup.channels).forEach((channels) => {\n            tier.channels[channels] =\n              (tier.channels[channels] || 0) + audioGroup.channels[channels];\n          });\n        });\n      }\n      return tiers;\n    }, {});\n}\n\nexport function findMatchingOption(\n  option: MediaPlaylist | AudioSelectionOption | SubtitleSelectionOption,\n  tracks: MediaPlaylist[],\n  matchPredicate?: (\n    option: MediaPlaylist | AudioSelectionOption | SubtitleSelectionOption,\n    track: MediaPlaylist,\n  ) => boolean,\n): number {\n  if ('attrs' in option) {\n    const index = tracks.indexOf(option);\n    if (index !== -1) {\n      return index;\n    }\n  }\n  for (let i = 0; i < tracks.length; i++) {\n    const track = tracks[i];\n    if (matchesOption(option, track, matchPredicate)) {\n      return i;\n    }\n  }\n  return -1;\n}\n\nexport function matchesOption(\n  option: MediaPlaylist | AudioSelectionOption | SubtitleSelectionOption,\n  track: MediaPlaylist,\n  matchPredicate?: (\n    option: MediaPlaylist | AudioSelectionOption | SubtitleSelectionOption,\n    track: MediaPlaylist,\n  ) => boolean,\n): boolean {\n  const {\n    groupId,\n    name,\n    lang,\n    assocLang,\n    characteristics,\n    default: isDefault,\n  } = option;\n  const forced = (option as SubtitleSelectionOption).forced;\n  return (\n    (groupId === undefined || track.groupId === groupId) &&\n    (name === undefined || track.name === name) &&\n    (lang === undefined || track.lang === lang) &&\n    (lang === undefined || track.assocLang === assocLang) &&\n    (isDefault === undefined || track.default === isDefault) &&\n    (forced === undefined || track.forced === forced) &&\n    (characteristics === undefined ||\n      characteristicsMatch(characteristics, track.characteristics)) &&\n    (matchPredicate === undefined || matchPredicate(option, track))\n  );\n}\n\nfunction characteristicsMatch(\n  characteristicsA: string,\n  characteristicsB: string = '',\n): boolean {\n  const arrA = characteristicsA.split(',');\n  const arrB = characteristicsB.split(',');\n  // Expects each item to be unique:\n  return (\n    arrA.length === arrB.length && !arrA.some((el) => arrB.indexOf(el) === -1)\n  );\n}\n\nexport function audioMatchPredicate(\n  option: MediaPlaylist | AudioSelectionOption,\n  track: MediaPlaylist,\n) {\n  const { audioCodec, channels } = option;\n  return (\n    (audioCodec === undefined ||\n      (track.audioCodec || '').substring(0, 4) ===\n        audioCodec.substring(0, 4)) &&\n    (channels === undefined || channels === (track.channels || '2'))\n  );\n}\n\nexport function findClosestLevelWithAudioGroup(\n  option: MediaPlaylist | AudioSelectionOption,\n  levels: Level[],\n  allAudioTracks: MediaPlaylist[],\n  searchIndex: number,\n  matchPredicate: (\n    option: MediaPlaylist | AudioSelectionOption,\n    track: MediaPlaylist,\n  ) => boolean,\n): number {\n  const currentLevel = levels[searchIndex];\n  // Are there variants with same URI as current level?\n  // If so, find a match that does not require any level URI change\n  const variants = levels.reduce(\n    (variantMap: { [uri: string]: number[] }, level, index) => {\n      const uri = level.uri;\n      const renditions = variantMap[uri] || (variantMap[uri] = []);\n      renditions.push(index);\n      return variantMap;\n    },\n    {},\n  );\n  const renditions = variants[currentLevel.uri];\n  if (renditions.length > 1) {\n    searchIndex = Math.max.apply(Math, renditions);\n  }\n  // Find best match\n  const currentVideoRange = currentLevel.videoRange;\n  const currentFrameRate = currentLevel.frameRate;\n  const currentVideoCodec = currentLevel.codecSet.substring(0, 4);\n  const matchingVideo = searchDownAndUpList(\n    levels,\n    searchIndex,\n    (level: Level) => {\n      if (\n        level.videoRange !== currentVideoRange ||\n        level.frameRate !== currentFrameRate ||\n        level.codecSet.substring(0, 4) !== currentVideoCodec\n      ) {\n        return false;\n      }\n      const audioGroups = level.audioGroups;\n      const tracks = allAudioTracks.filter(\n        (track): boolean =>\n          !audioGroups || audioGroups.indexOf(track.groupId) !== -1,\n      );\n      return findMatchingOption(option, tracks, matchPredicate) > -1;\n    },\n  );\n  if (matchingVideo > -1) {\n    return matchingVideo;\n  }\n  return searchDownAndUpList(levels, searchIndex, (level: Level) => {\n    const audioGroups = level.audioGroups;\n    const tracks = allAudioTracks.filter(\n      (track): boolean =>\n        !audioGroups || audioGroups.indexOf(track.groupId) !== -1,\n    );\n    return findMatchingOption(option, tracks, matchPredicate) > -1;\n  });\n}\n\nfunction searchDownAndUpList(\n  arr: any[],\n  searchIndex: number,\n  predicate: (item: any) => boolean,\n): number {\n  for (let i = searchIndex; i > -1; i--) {\n    if (predicate(arr[i])) {\n      return i;\n    }\n  }\n  for (let i = searchIndex + 1; i < arr.length; i++) {\n    if (predicate(arr[i])) {\n      return i;\n    }\n  }\n  return -1;\n}\n", "import EwmaBandWidthEstimator from '../utils/ewma-bandwidth-estimator';\nimport { Events } from '../events';\nimport { ErrorDetails } from '../errors';\nimport { PlaylistLevelType } from '../types/loader';\nimport { logger } from '../utils/logger';\nimport {\n  SUPPORTED_INFO_DEFAULT,\n  getMediaDecodingInfoPromise,\n  requiresMediaCapabilitiesDecodingInfo,\n} from '../utils/mediacapabilities-helper';\nimport {\n  getAudioTracksByGroup,\n  getCodecTiers,\n  getStartCodecTier,\n  type AudioTracksByGroup,\n  type CodecSetTier,\n} from '../utils/rendition-helper';\nimport type { Fragment } from '../loader/fragment';\nimport type { Part } from '../loader/fragment';\nimport type { Level, VideoRange } from '../types/level';\nimport type { LoaderStats } from '../types/loader';\nimport type Hls from '../hls';\nimport type {\n  FragLoadingData,\n  FragLoadedData,\n  FragBufferedData,\n  LevelLoadedData,\n  LevelSwitchingData,\n  ManifestLoadingData,\n  ErrorData,\n} from '../types/events';\nimport type { AbrComponentAPI } from '../types/component-api';\n\nclass AbrController implements AbrComponentAPI {\n  protected hls: Hls;\n  private lastLevelLoadSec: number = 0;\n  private lastLoadedFragLevel: number = -1;\n  private firstSelection: number = -1;\n  private _nextAutoLevel: number = -1;\n  private nextAutoLevelKey: string = '';\n  private audioTracksByGroup: AudioTracksByGroup | null = null;\n  private codecTiers: Record<string, CodecSetTier> | null = null;\n  private timer: number = -1;\n  private fragCurrent: Fragment | null = null;\n  private partCurrent: Part | null = null;\n  private bitrateTestDelay: number = 0;\n\n  public bwEstimator: EwmaBandWidthEstimator;\n\n  constructor(hls: Hls) {\n    this.hls = hls;\n    this.bwEstimator = this.initEstimator();\n    this.registerListeners();\n  }\n\n  public resetEstimator(abrEwmaDefaultEstimate?: number) {\n    if (abrEwmaDefaultEstimate) {\n      logger.log(`setting initial bwe to ${abrEwmaDefaultEstimate}`);\n      this.hls.config.abrEwmaDefaultEstimate = abrEwmaDefaultEstimate;\n    }\n    this.firstSelection = -1;\n    this.bwEstimator = this.initEstimator();\n  }\n\n  private initEstimator(): EwmaBandWidthEstimator {\n    const config = this.hls.config;\n    return new EwmaBandWidthEstimator(\n      config.abrEwmaSlowVoD,\n      config.abrEwmaFastVoD,\n      config.abrEwmaDefaultEstimate,\n    );\n  }\n\n  protected registerListeners() {\n    const { hls } = this;\n    hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    hls.on(Events.FRAG_LOADING, this.onFragLoading, this);\n    hls.on(Events.FRAG_LOADED, this.onFragLoaded, this);\n    hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);\n    hls.on(Events.LEVEL_SWITCHING, this.onLevelSwitching, this);\n    hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);\n    hls.on(Events.LEVELS_UPDATED, this.onLevelsUpdated, this);\n    hls.on(Events.MAX_AUTO_LEVEL_UPDATED, this.onMaxAutoLevelUpdated, this);\n    hls.on(Events.ERROR, this.onError, this);\n  }\n\n  protected unregisterListeners() {\n    const { hls } = this;\n    if (!hls) {\n      return;\n    }\n    hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    hls.off(Events.FRAG_LOADING, this.onFragLoading, this);\n    hls.off(Events.FRAG_LOADED, this.onFragLoaded, this);\n    hls.off(Events.FRAG_BUFFERED, this.onFragBuffered, this);\n    hls.off(Events.LEVEL_SWITCHING, this.onLevelSwitching, this);\n    hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);\n    hls.off(Events.LEVELS_UPDATED, this.onLevelsUpdated, this);\n    hls.off(Events.MAX_AUTO_LEVEL_UPDATED, this.onMaxAutoLevelUpdated, this);\n    hls.off(Events.ERROR, this.onError, this);\n  }\n\n  public destroy() {\n    this.unregisterListeners();\n    this.clearTimer();\n    // @ts-ignore\n    this.hls = this._abandonRulesCheck = null;\n    this.fragCurrent = this.partCurrent = null;\n  }\n\n  protected onManifestLoading(\n    event: Events.MANIFEST_LOADING,\n    data: ManifestLoadingData,\n  ) {\n    this.lastLoadedFragLevel = -1;\n    this.firstSelection = -1;\n    this.lastLevelLoadSec = 0;\n    this.fragCurrent = this.partCurrent = null;\n    this.onLevelsUpdated();\n    this.clearTimer();\n  }\n\n  private onLevelsUpdated() {\n    if (this.lastLoadedFragLevel > -1 && this.fragCurrent) {\n      this.lastLoadedFragLevel = this.fragCurrent.level;\n    }\n    this._nextAutoLevel = -1;\n    this.onMaxAutoLevelUpdated();\n    this.codecTiers = null;\n    this.audioTracksByGroup = null;\n  }\n\n  private onMaxAutoLevelUpdated() {\n    this.firstSelection = -1;\n    this.nextAutoLevelKey = '';\n  }\n\n  protected onFragLoading(event: Events.FRAG_LOADING, data: FragLoadingData) {\n    const frag = data.frag;\n    if (this.ignoreFragment(frag)) {\n      return;\n    }\n    if (!frag.bitrateTest) {\n      this.fragCurrent = frag;\n      this.partCurrent = data.part ?? null;\n    }\n    this.clearTimer();\n    this.timer = self.setInterval(this._abandonRulesCheck, 100);\n  }\n\n  protected onLevelSwitching(\n    event: Events.LEVEL_SWITCHING,\n    data: LevelSwitchingData,\n  ): void {\n    this.clearTimer();\n  }\n\n  protected onError(event: Events.ERROR, data: ErrorData) {\n    if (data.fatal) {\n      return;\n    }\n    switch (data.details) {\n      case ErrorDetails.BUFFER_ADD_CODEC_ERROR:\n      case ErrorDetails.BUFFER_APPEND_ERROR:\n        // Reset last loaded level so that a new selection can be made after calling recoverMediaError\n        this.lastLoadedFragLevel = -1;\n        this.firstSelection = -1;\n        break;\n      case ErrorDetails.FRAG_LOAD_TIMEOUT: {\n        const frag = data.frag;\n        const { fragCurrent, partCurrent: part } = this;\n        if (\n          frag &&\n          fragCurrent &&\n          frag.sn === fragCurrent.sn &&\n          frag.level === fragCurrent.level\n        ) {\n          const now = performance.now();\n          const stats: LoaderStats = part ? part.stats : frag.stats;\n          const timeLoading = now - stats.loading.start;\n          const ttfb = stats.loading.first\n            ? stats.loading.first - stats.loading.start\n            : -1;\n          const loadedFirstByte = stats.loaded && ttfb > -1;\n          if (loadedFirstByte) {\n            const ttfbEstimate = this.bwEstimator.getEstimateTTFB();\n            this.bwEstimator.sample(\n              timeLoading - Math.min(ttfbEstimate, ttfb),\n              stats.loaded,\n            );\n          } else {\n            this.bwEstimator.sampleTTFB(timeLoading);\n          }\n        }\n        break;\n      }\n    }\n  }\n\n  private getTimeToLoadFrag(\n    timeToFirstByteSec: number,\n    bandwidth: number,\n    fragSizeBits: number,\n    isSwitch: boolean,\n  ): number {\n    const fragLoadSec = timeToFirstByteSec + fragSizeBits / bandwidth;\n    const playlistLoadSec = isSwitch ? this.lastLevelLoadSec : 0;\n    return fragLoadSec + playlistLoadSec;\n  }\n\n  protected onLevelLoaded(event: Events.LEVEL_LOADED, data: LevelLoadedData) {\n    const config = this.hls.config;\n    const { loading } = data.stats;\n    const timeLoadingMs = loading.end - loading.start;\n    if (Number.isFinite(timeLoadingMs)) {\n      this.lastLevelLoadSec = timeLoadingMs / 1000;\n    }\n    if (data.details.live) {\n      this.bwEstimator.update(config.abrEwmaSlowLive, config.abrEwmaFastLive);\n    } else {\n      this.bwEstimator.update(config.abrEwmaSlowVoD, config.abrEwmaFastVoD);\n    }\n  }\n\n  /*\n      This method monitors the download rate of the current fragment, and will downswitch if that fragment will not load\n      quickly enough to prevent underbuffering\n    */\n  private _abandonRulesCheck = () => {\n    const { fragCurrent: frag, partCurrent: part, hls } = this;\n    const { autoLevelEnabled, media } = hls;\n    if (!frag || !media) {\n      return;\n    }\n\n    const now = performance.now();\n    const stats: LoaderStats = part ? part.stats : frag.stats;\n    const duration = part ? part.duration : frag.duration;\n    const timeLoading = now - stats.loading.start;\n    const minAutoLevel = hls.minAutoLevel;\n    // If frag loading is aborted, complete, or from lowest level, stop timer and return\n    if (\n      stats.aborted ||\n      (stats.loaded && stats.loaded === stats.total) ||\n      frag.level <= minAutoLevel\n    ) {\n      this.clearTimer();\n      // reset forced auto level value so that next level will be selected\n      this._nextAutoLevel = -1;\n      return;\n    }\n\n    // This check only runs if we're in ABR mode and actually playing\n    if (\n      !autoLevelEnabled ||\n      media.paused ||\n      !media.playbackRate ||\n      !media.readyState\n    ) {\n      return;\n    }\n\n    const bufferInfo = hls.mainForwardBufferInfo;\n    if (bufferInfo === null) {\n      return;\n    }\n\n    const ttfbEstimate = this.bwEstimator.getEstimateTTFB();\n    const playbackRate = Math.abs(media.playbackRate);\n    // To maintain stable adaptive playback, only begin monitoring frag loading after half or more of its playback duration has passed\n    if (\n      timeLoading <=\n      Math.max(ttfbEstimate, 1000 * (duration / (playbackRate * 2)))\n    ) {\n      return;\n    }\n\n    // bufferStarvationDelay is an estimate of the amount time (in seconds) it will take to exhaust the buffer\n    const bufferStarvationDelay = bufferInfo.len / playbackRate;\n    const ttfb = stats.loading.first\n      ? stats.loading.first - stats.loading.start\n      : -1;\n    const loadedFirstByte = stats.loaded && ttfb > -1;\n    const bwEstimate: number = this.getBwEstimate();\n    const levels = hls.levels;\n    const level = levels[frag.level];\n    const expectedLen =\n      stats.total ||\n      Math.max(stats.loaded, Math.round((duration * level.averageBitrate) / 8));\n    let timeStreaming = loadedFirstByte ? timeLoading - ttfb : timeLoading;\n    if (timeStreaming < 1 && loadedFirstByte) {\n      timeStreaming = Math.min(timeLoading, (stats.loaded * 8) / bwEstimate);\n    }\n    const loadRate = loadedFirstByte\n      ? (stats.loaded * 1000) / timeStreaming\n      : 0;\n    // fragLoadDelay is an estimate of the time (in seconds) it will take to buffer the remainder of the fragment\n    const fragLoadedDelay = loadRate\n      ? (expectedLen - stats.loaded) / loadRate\n      : (expectedLen * 8) / bwEstimate + ttfbEstimate / 1000;\n    // Only downswitch if the time to finish loading the current fragment is greater than the amount of buffer left\n    if (fragLoadedDelay <= bufferStarvationDelay) {\n      return;\n    }\n\n    const bwe = loadRate ? loadRate * 8 : bwEstimate;\n    let fragLevelNextLoadedDelay: number = Number.POSITIVE_INFINITY;\n    let nextLoadLevel: number;\n    // Iterate through lower level and try to find the largest one that avoids rebuffering\n    for (\n      nextLoadLevel = frag.level - 1;\n      nextLoadLevel > minAutoLevel;\n      nextLoadLevel--\n    ) {\n      // compute time to load next fragment at lower level\n      // 8 = bits per byte (bps/Bps)\n      const levelNextBitrate = levels[nextLoadLevel].maxBitrate;\n      fragLevelNextLoadedDelay = this.getTimeToLoadFrag(\n        ttfbEstimate / 1000,\n        bwe,\n        duration * levelNextBitrate,\n        !levels[nextLoadLevel].details,\n      );\n      if (fragLevelNextLoadedDelay < bufferStarvationDelay) {\n        break;\n      }\n    }\n    // Only emergency switch down if it takes less time to load a new fragment at lowest level instead of continuing\n    // to load the current one\n    if (fragLevelNextLoadedDelay >= fragLoadedDelay) {\n      return;\n    }\n\n    // if estimated load time of new segment is completely unreasonable, ignore and do not emergency switch down\n    if (fragLevelNextLoadedDelay > duration * 10) {\n      return;\n    }\n    hls.nextLoadLevel = hls.nextAutoLevel = nextLoadLevel;\n    if (loadedFirstByte) {\n      // If there has been loading progress, sample bandwidth using loading time offset by minimum TTFB time\n      this.bwEstimator.sample(\n        timeLoading - Math.min(ttfbEstimate, ttfb),\n        stats.loaded,\n      );\n    } else {\n      // If there has been no loading progress, sample TTFB\n      this.bwEstimator.sampleTTFB(timeLoading);\n    }\n    const nextLoadLevelBitrate = levels[nextLoadLevel].maxBitrate;\n    if (\n      this.getBwEstimate() * this.hls.config.abrBandWidthUpFactor >\n      nextLoadLevelBitrate\n    ) {\n      this.resetEstimator(nextLoadLevelBitrate);\n    }\n\n    this.clearTimer();\n    logger.warn(`[abr] Fragment ${frag.sn}${\n      part ? ' part ' + part.index : ''\n    } of level ${frag.level} is loading too slowly;\n      Time to underbuffer: ${bufferStarvationDelay.toFixed(3)} s\n      Estimated load time for current fragment: ${fragLoadedDelay.toFixed(3)} s\n      Estimated load time for down switch fragment: ${fragLevelNextLoadedDelay.toFixed(\n        3,\n      )} s\n      TTFB estimate: ${ttfb | 0} ms\n      Current BW estimate: ${\n        Number.isFinite(bwEstimate) ? bwEstimate | 0 : 'Unknown'\n      } bps\n      New BW estimate: ${this.getBwEstimate() | 0} bps\n      Switching to level ${nextLoadLevel} @ ${nextLoadLevelBitrate | 0} bps`);\n    hls.trigger(Events.FRAG_LOAD_EMERGENCY_ABORTED, { frag, part, stats });\n  };\n\n  protected onFragLoaded(\n    event: Events.FRAG_LOADED,\n    { frag, part }: FragLoadedData,\n  ) {\n    const stats = part ? part.stats : frag.stats;\n    if (frag.type === PlaylistLevelType.MAIN) {\n      this.bwEstimator.sampleTTFB(stats.loading.first - stats.loading.start);\n    }\n    if (this.ignoreFragment(frag)) {\n      return;\n    }\n    // stop monitoring bw once frag loaded\n    this.clearTimer();\n    // reset forced auto level value so that next level will be selected\n    if (frag.level === this._nextAutoLevel) {\n      this._nextAutoLevel = -1;\n    }\n    this.firstSelection = -1;\n\n    // compute level average bitrate\n    if (this.hls.config.abrMaxWithRealBitrate) {\n      const duration = part ? part.duration : frag.duration;\n      const level = this.hls.levels[frag.level];\n      const loadedBytes =\n        (level.loaded ? level.loaded.bytes : 0) + stats.loaded;\n      const loadedDuration =\n        (level.loaded ? level.loaded.duration : 0) + duration;\n      level.loaded = { bytes: loadedBytes, duration: loadedDuration };\n      level.realBitrate = Math.round((8 * loadedBytes) / loadedDuration);\n    }\n    if (frag.bitrateTest) {\n      const fragBufferedData: FragBufferedData = {\n        stats,\n        frag,\n        part,\n        id: frag.type,\n      };\n      this.onFragBuffered(Events.FRAG_BUFFERED, fragBufferedData);\n      frag.bitrateTest = false;\n    } else {\n      // store level id after successful fragment load for playback\n      this.lastLoadedFragLevel = frag.level;\n    }\n  }\n\n  protected onFragBuffered(\n    event: Events.FRAG_BUFFERED,\n    data: FragBufferedData,\n  ) {\n    const { frag, part } = data;\n    const stats = part?.stats.loaded ? part.stats : frag.stats;\n\n    if (stats.aborted) {\n      return;\n    }\n    if (this.ignoreFragment(frag)) {\n      return;\n    }\n    // Use the difference between parsing and request instead of buffering and request to compute fragLoadingProcessing;\n    // rationale is that buffer appending only happens once media is attached. This can happen when config.startFragPrefetch\n    // is used. If we used buffering in that case, our BW estimate sample will be very large.\n    const processingMs =\n      stats.parsing.end -\n      stats.loading.start -\n      Math.min(\n        stats.loading.first - stats.loading.start,\n        this.bwEstimator.getEstimateTTFB(),\n      );\n    this.bwEstimator.sample(processingMs, stats.loaded);\n    stats.bwEstimate = this.getBwEstimate();\n    if (frag.bitrateTest) {\n      this.bitrateTestDelay = processingMs / 1000;\n    } else {\n      this.bitrateTestDelay = 0;\n    }\n  }\n\n  private ignoreFragment(frag: Fragment): boolean {\n    // Only count non-alt-audio frags which were actually buffered in our BW calculations\n    return frag.type !== PlaylistLevelType.MAIN || frag.sn === 'initSegment';\n  }\n\n  public clearTimer() {\n    if (this.timer > -1) {\n      self.clearInterval(this.timer);\n      this.timer = -1;\n    }\n  }\n\n  public get firstAutoLevel(): number {\n    const { maxAutoLevel, minAutoLevel } = this.hls;\n    const bwEstimate = this.getBwEstimate();\n    const maxStartDelay = this.hls.config.maxStarvationDelay;\n    const abrAutoLevel = this.findBestLevel(\n      bwEstimate,\n      minAutoLevel,\n      maxAutoLevel,\n      0,\n      maxStartDelay,\n      1,\n      1,\n    );\n    if (abrAutoLevel > -1) {\n      return abrAutoLevel;\n    }\n    const firstLevel = this.hls.firstLevel;\n    const clamped = Math.min(Math.max(firstLevel, minAutoLevel), maxAutoLevel);\n    logger.warn(\n      `[abr] Could not find best starting auto level. Defaulting to first in playlist ${firstLevel} clamped to ${clamped}`,\n    );\n    return clamped;\n  }\n\n  public get forcedAutoLevel(): number {\n    if (this.nextAutoLevelKey) {\n      return -1;\n    }\n    return this._nextAutoLevel;\n  }\n\n  // return next auto level\n  public get nextAutoLevel(): number {\n    const forcedAutoLevel = this.forcedAutoLevel;\n    const bwEstimator = this.bwEstimator;\n    const useEstimate = bwEstimator.canEstimate();\n    const loadedFirstFrag = this.lastLoadedFragLevel > -1;\n    // in case next auto level has been forced, and bw not available or not reliable, return forced value\n    if (\n      forcedAutoLevel !== -1 &&\n      (!useEstimate ||\n        !loadedFirstFrag ||\n        this.nextAutoLevelKey === this.getAutoLevelKey())\n    ) {\n      return forcedAutoLevel;\n    }\n\n    // compute next level using ABR logic\n    const nextABRAutoLevel =\n      useEstimate && loadedFirstFrag\n        ? this.getNextABRAutoLevel()\n        : this.firstAutoLevel;\n\n    // use forced auto level while it hasn't errored more than ABR selection\n    if (forcedAutoLevel !== -1) {\n      const levels = this.hls.levels;\n      if (\n        levels.length > Math.max(forcedAutoLevel, nextABRAutoLevel) &&\n        levels[forcedAutoLevel].loadError <= levels[nextABRAutoLevel].loadError\n      ) {\n        return forcedAutoLevel;\n      }\n    }\n\n    // save result until state has changed\n    this._nextAutoLevel = nextABRAutoLevel;\n    this.nextAutoLevelKey = this.getAutoLevelKey();\n\n    return nextABRAutoLevel;\n  }\n\n  private getAutoLevelKey(): string {\n    return `${this.getBwEstimate()}_${this.getStarvationDelay().toFixed(2)}`;\n  }\n\n  private getNextABRAutoLevel(): number {\n    const { fragCurrent, partCurrent, hls } = this;\n    const { maxAutoLevel, config, minAutoLevel } = hls;\n    const currentFragDuration = partCurrent\n      ? partCurrent.duration\n      : fragCurrent\n        ? fragCurrent.duration\n        : 0;\n    const avgbw = this.getBwEstimate();\n    // bufferStarvationDelay is the wall-clock time left until the playback buffer is exhausted.\n    const bufferStarvationDelay = this.getStarvationDelay();\n\n    let bwFactor = config.abrBandWidthFactor;\n    let bwUpFactor = config.abrBandWidthUpFactor;\n\n    // First, look to see if we can find a level matching with our avg bandwidth AND that could also guarantee no rebuffering at all\n    if (bufferStarvationDelay) {\n      const bestLevel = this.findBestLevel(\n        avgbw,\n        minAutoLevel,\n        maxAutoLevel,\n        bufferStarvationDelay,\n        0,\n        bwFactor,\n        bwUpFactor,\n      );\n      if (bestLevel >= 0) {\n        return bestLevel;\n      }\n    }\n    // not possible to get rid of rebuffering... try to find level that will guarantee less than maxStarvationDelay of rebuffering\n    let maxStarvationDelay = currentFragDuration\n      ? Math.min(currentFragDuration, config.maxStarvationDelay)\n      : config.maxStarvationDelay;\n\n    if (!bufferStarvationDelay) {\n      // in case buffer is empty, let's check if previous fragment was loaded to perform a bitrate test\n      const bitrateTestDelay = this.bitrateTestDelay;\n      if (bitrateTestDelay) {\n        // if it is the case, then we need to adjust our max starvation delay using maxLoadingDelay config value\n        // max video loading delay used in  automatic start level selection :\n        // in that mode ABR controller will ensure that video loading time (ie the time to fetch the first fragment at lowest quality level +\n        // the time to fetch the fragment at the appropriate quality level is less than ```maxLoadingDelay``` )\n        // cap maxLoadingDelay and ensure it is not bigger 'than bitrate test' frag duration\n        const maxLoadingDelay = currentFragDuration\n          ? Math.min(currentFragDuration, config.maxLoadingDelay)\n          : config.maxLoadingDelay;\n        maxStarvationDelay = maxLoadingDelay - bitrateTestDelay;\n        logger.info(\n          `[abr] bitrate test took ${Math.round(\n            1000 * bitrateTestDelay,\n          )}ms, set first fragment max fetchDuration to ${Math.round(\n            1000 * maxStarvationDelay,\n          )} ms`,\n        );\n        // don't use conservative factor on bitrate test\n        bwFactor = bwUpFactor = 1;\n      }\n    }\n    const bestLevel = this.findBestLevel(\n      avgbw,\n      minAutoLevel,\n      maxAutoLevel,\n      bufferStarvationDelay,\n      maxStarvationDelay,\n      bwFactor,\n      bwUpFactor,\n    );\n    logger.info(\n      `[abr] ${\n        bufferStarvationDelay ? 'rebuffering expected' : 'buffer is empty'\n      }, optimal quality level ${bestLevel}`,\n    );\n    if (bestLevel > -1) {\n      return bestLevel;\n    }\n    // If no matching level found, see if min auto level would be a better option\n    const minLevel = hls.levels[minAutoLevel];\n    const autoLevel = hls.levels[hls.loadLevel];\n    if (minLevel?.bitrate < autoLevel?.bitrate) {\n      return minAutoLevel;\n    }\n    // or if bitrate is not lower, continue to use loadLevel\n    return hls.loadLevel;\n  }\n\n  private getStarvationDelay(): number {\n    const hls = this.hls;\n    const media = hls.media;\n    if (!media) {\n      return Infinity;\n    }\n    // playbackRate is the absolute value of the playback rate; if media.playbackRate is 0, we use 1 to load as\n    // if we're playing back at the normal rate.\n    const playbackRate =\n      media && media.playbackRate !== 0 ? Math.abs(media.playbackRate) : 1.0;\n    const bufferInfo = hls.mainForwardBufferInfo;\n    return (bufferInfo ? bufferInfo.len : 0) / playbackRate;\n  }\n\n  private getBwEstimate(): number {\n    return this.bwEstimator.canEstimate()\n      ? this.bwEstimator.getEstimate()\n      : this.hls.config.abrEwmaDefaultEstimate;\n  }\n\n  private findBestLevel(\n    currentBw: number,\n    minAutoLevel: number,\n    maxAutoLevel: number,\n    bufferStarvationDelay: number,\n    maxStarvationDelay: number,\n    bwFactor: number,\n    bwUpFactor: number,\n  ): number {\n    const maxFetchDuration: number = bufferStarvationDelay + maxStarvationDelay;\n    const lastLoadedFragLevel = this.lastLoadedFragLevel;\n    const selectionBaseLevel =\n      lastLoadedFragLevel === -1 ? this.hls.firstLevel : lastLoadedFragLevel;\n    const { fragCurrent, partCurrent } = this;\n    const { levels, allAudioTracks, loadLevel, config } = this.hls;\n    if (levels.length === 1) {\n      return 0;\n    }\n    const level: Level | undefined = levels[selectionBaseLevel];\n    const live = !!level?.details?.live;\n    const firstSelection = loadLevel === -1 || lastLoadedFragLevel === -1;\n    let currentCodecSet: string | undefined;\n    let currentVideoRange: VideoRange | undefined = 'SDR';\n    let currentFrameRate = level?.frameRate || 0;\n\n    const { audioPreference, videoPreference } = config;\n    const audioTracksByGroup =\n      this.audioTracksByGroup ||\n      (this.audioTracksByGroup = getAudioTracksByGroup(allAudioTracks));\n    if (firstSelection) {\n      if (this.firstSelection !== -1) {\n        return this.firstSelection;\n      }\n      const codecTiers =\n        this.codecTiers ||\n        (this.codecTiers = getCodecTiers(\n          levels,\n          audioTracksByGroup,\n          minAutoLevel,\n          maxAutoLevel,\n        ));\n      const startTier = getStartCodecTier(\n        codecTiers,\n        currentVideoRange,\n        currentBw,\n        audioPreference,\n        videoPreference,\n      );\n      const { codecSet, videoRanges, minFramerate, minBitrate, preferHDR } =\n        startTier;\n      currentCodecSet = codecSet;\n      currentVideoRange = preferHDR\n        ? videoRanges[videoRanges.length - 1]\n        : videoRanges[0];\n      currentFrameRate = minFramerate;\n      currentBw = Math.max(currentBw, minBitrate);\n      logger.log(`[abr] picked start tier ${JSON.stringify(startTier)}`);\n    } else {\n      currentCodecSet = level?.codecSet;\n      currentVideoRange = level?.videoRange;\n    }\n\n    const currentFragDuration = partCurrent\n      ? partCurrent.duration\n      : fragCurrent\n        ? fragCurrent.duration\n        : 0;\n\n    const ttfbEstimateSec = this.bwEstimator.getEstimateTTFB() / 1000;\n    const levelsSkipped: number[] = [];\n    for (let i = maxAutoLevel; i >= minAutoLevel; i--) {\n      const levelInfo = levels[i];\n      const upSwitch = i > selectionBaseLevel;\n      if (!levelInfo) {\n        continue;\n      }\n      if (\n        __USE_MEDIA_CAPABILITIES__ &&\n        config.useMediaCapabilities &&\n        !levelInfo.supportedResult &&\n        !levelInfo.supportedPromise\n      ) {\n        const mediaCapabilities = navigator.mediaCapabilities as\n          | MediaCapabilities\n          | undefined;\n        if (\n          typeof mediaCapabilities?.decodingInfo === 'function' &&\n          requiresMediaCapabilitiesDecodingInfo(\n            levelInfo,\n            audioTracksByGroup,\n            currentVideoRange,\n            currentFrameRate,\n            currentBw,\n            audioPreference,\n          )\n        ) {\n          levelInfo.supportedPromise = getMediaDecodingInfoPromise(\n            levelInfo,\n            audioTracksByGroup,\n            mediaCapabilities,\n          );\n          levelInfo.supportedPromise.then((decodingInfo) => {\n            if (!this.hls) {\n              return;\n            }\n            levelInfo.supportedResult = decodingInfo;\n            const levels = this.hls.levels;\n            const index = levels.indexOf(levelInfo);\n            if (decodingInfo.error) {\n              logger.warn(\n                `[abr] MediaCapabilities decodingInfo error: \"${\n                  decodingInfo.error\n                }\" for level ${index} ${JSON.stringify(decodingInfo)}`,\n              );\n            } else if (!decodingInfo.supported) {\n              logger.warn(\n                `[abr] Unsupported MediaCapabilities decodingInfo result for level ${index} ${JSON.stringify(\n                  decodingInfo,\n                )}`,\n              );\n              if (index > -1 && levels.length > 1) {\n                logger.log(`[abr] Removing unsupported level ${index}`);\n                this.hls.removeLevel(index);\n              }\n            }\n          });\n        } else {\n          levelInfo.supportedResult = SUPPORTED_INFO_DEFAULT;\n        }\n      }\n\n      // skip candidates which change codec-family or video-range,\n      // and which decrease or increase frame-rate for up and down-switch respectfully\n      if (\n        (currentCodecSet && levelInfo.codecSet !== currentCodecSet) ||\n        (currentVideoRange && levelInfo.videoRange !== currentVideoRange) ||\n        (upSwitch && currentFrameRate > levelInfo.frameRate) ||\n        (!upSwitch &&\n          currentFrameRate > 0 &&\n          currentFrameRate < levelInfo.frameRate) ||\n        (levelInfo.supportedResult &&\n          !levelInfo.supportedResult.decodingInfoResults?.[0].smooth)\n      ) {\n        levelsSkipped.push(i);\n        continue;\n      }\n\n      const levelDetails = levelInfo.details;\n      const avgDuration =\n        (partCurrent\n          ? levelDetails?.partTarget\n          : levelDetails?.averagetargetduration) || currentFragDuration;\n\n      let adjustedbw: number;\n      // follow algorithm captured from stagefright :\n      // https://android.googlesource.com/platform/frameworks/av/+/master/media/libstagefright/httplive/LiveSession.cpp\n      // Pick the highest bandwidth stream below or equal to estimated bandwidth.\n      // consider only 80% of the available bandwidth, but if we are switching up,\n      // be even more conservative (70%) to avoid overestimating and immediately\n      // switching back.\n      if (!upSwitch) {\n        adjustedbw = bwFactor * currentBw;\n      } else {\n        adjustedbw = bwUpFactor * currentBw;\n      }\n\n      // Use average bitrate when starvation delay (buffer length) is gt or eq two segment durations and rebuffering is not expected (maxStarvationDelay > 0)\n      const bitrate: number =\n        currentFragDuration &&\n        bufferStarvationDelay >= currentFragDuration * 2 &&\n        maxStarvationDelay === 0\n          ? levels[i].averageBitrate\n          : levels[i].maxBitrate;\n      const fetchDuration: number = this.getTimeToLoadFrag(\n        ttfbEstimateSec,\n        adjustedbw,\n        bitrate * avgDuration,\n        levelDetails === undefined,\n      );\n\n      const canSwitchWithinTolerance =\n        // if adjusted bw is greater than level bitrate AND\n        adjustedbw >= bitrate &&\n        // no level change, or new level has no error history\n        (i === lastLoadedFragLevel ||\n          (levelInfo.loadError === 0 && levelInfo.fragmentError === 0)) &&\n        // fragment fetchDuration unknown OR live stream OR fragment fetchDuration less than max allowed fetch duration, then this level matches\n        // we don't account for max Fetch Duration for live streams, this is to avoid switching down when near the edge of live sliding window ...\n        // special case to support startLevel = -1 (bitrateTest) on live streams : in that case we should not exit loop so that findBestLevel will return -1\n        (fetchDuration <= ttfbEstimateSec ||\n          !Number.isFinite(fetchDuration) ||\n          (live && !this.bitrateTestDelay) ||\n          fetchDuration < maxFetchDuration);\n      if (canSwitchWithinTolerance) {\n        const forcedAutoLevel = this.forcedAutoLevel;\n        if (\n          i !== loadLevel &&\n          (forcedAutoLevel === -1 || forcedAutoLevel !== loadLevel)\n        ) {\n          if (levelsSkipped.length) {\n            logger.trace(\n              `[abr] Skipped level(s) ${levelsSkipped.join(\n                ',',\n              )} of ${maxAutoLevel} max with CODECS and VIDEO-RANGE:\"${\n                levels[levelsSkipped[0]].codecs\n              }\" ${levels[levelsSkipped[0]].videoRange}; not compatible with \"${\n                level.codecs\n              }\" ${currentVideoRange}`,\n            );\n          }\n          logger.info(\n            `[abr] switch candidate:${selectionBaseLevel}->${i} adjustedbw(${Math.round(\n              adjustedbw,\n            )})-bitrate=${Math.round(\n              adjustedbw - bitrate,\n            )} ttfb:${ttfbEstimateSec.toFixed(\n              1,\n            )} avgDuration:${avgDuration.toFixed(\n              1,\n            )} maxFetchDuration:${maxFetchDuration.toFixed(\n              1,\n            )} fetchDuration:${fetchDuration.toFixed(\n              1,\n            )} firstSelection:${firstSelection} codecSet:${currentCodecSet} videoRange:${currentVideoRange} hls.loadLevel:${loadLevel}`,\n          );\n        }\n        if (firstSelection) {\n          this.firstSelection = i;\n        }\n        // as we are looping from highest to lowest, this will return the best achievable quality level\n        return i;\n      }\n    }\n    // not enough time budget even with quality level 0 ... rebuffering might happen\n    return -1;\n  }\n\n  public set nextAutoLevel(nextLevel: number) {\n    const { maxAutoLevel, minAutoLevel } = this.hls;\n    const value = Math.min(Math.max(nextLevel, minAutoLevel), maxAutoLevel);\n    if (this._nextAutoLevel !== value) {\n      this.nextAutoLevelKey = '';\n      this._nextAutoLevel = value;\n    }\n  }\n}\n\nexport default AbrController;\n", "/**\n * @ignore\n * Sub-class specialization of EventHandler base class.\n *\n * TaskLoop allows to schedule a task function being called (optionnaly repeatedly) on the main loop,\n * scheduled asynchroneously, avoiding recursive calls in the same tick.\n *\n * The task itself is implemented in `doTick`. It can be requested and called for single execution\n * using the `tick` method.\n *\n * It will be assured that the task execution method (`tick`) only gets called once per main loop \"tick\",\n * no matter how often it gets requested for execution. Execution in further ticks will be scheduled accordingly.\n *\n * If further execution requests have already been scheduled on the next tick, it can be checked with `hasNextTick`,\n * and cancelled with `clearNextTick`.\n *\n * The task can be scheduled as an interval repeatedly with a period as parameter (see `setInterval`, `clearInterval`).\n *\n * Sub-classes need to implement the `doTick` method which will effectively have the task execution routine.\n *\n * Further explanations:\n *\n * The baseclass has a `tick` method that will schedule the doTick call. It may be called synchroneously\n * only for a stack-depth of one. On re-entrant calls, sub-sequent calls are scheduled for next main loop ticks.\n *\n * When the task execution (`tick` method) is called in re-entrant way this is detected and\n * we are limiting the task execution per call stack to exactly one, but scheduling/post-poning further\n * task processing on the next main loop iteration (also known as \"next tick\" in the Node/JS runtime lingo).\n */\nexport default class TaskLoop {\n  private readonly _boundTick: () => void;\n  private _tickTimer: number | null = null;\n  private _tickInterval: number | null = null;\n  private _tickCallCount = 0;\n\n  constructor() {\n    this._boundTick = this.tick.bind(this);\n  }\n\n  public destroy() {\n    this.onHandlerDestroying();\n    this.onHandlerDestroyed();\n  }\n\n  protected onHandlerDestroying() {\n    // clear all timers before unregistering from event bus\n    this.clearNextTick();\n    this.clearInterval();\n  }\n\n  protected onHandlerDestroyed() {}\n\n  public hasInterval(): boolean {\n    return !!this._tickInterval;\n  }\n\n  public hasNextTick(): boolean {\n    return !!this._tickTimer;\n  }\n\n  /**\n   * @param millis - Interval time (ms)\n   * @eturns True when interval has been scheduled, false when already scheduled (no effect)\n   */\n  public setInterval(millis: number): boolean {\n    if (!this._tickInterval) {\n      this._tickCallCount = 0;\n      this._tickInterval = self.setInterval(this._boundTick, millis);\n      return true;\n    }\n    return false;\n  }\n\n  /**\n   * @returns True when interval was cleared, false when none was set (no effect)\n   */\n  public clearInterval(): boolean {\n    if (this._tickInterval) {\n      self.clearInterval(this._tickInterval);\n      this._tickInterval = null;\n      return true;\n    }\n    return false;\n  }\n\n  /**\n   * @returns True when timeout was cleared, false when none was set (no effect)\n   */\n  public clearNextTick(): boolean {\n    if (this._tickTimer) {\n      self.clearTimeout(this._tickTimer);\n      this._tickTimer = null;\n      return true;\n    }\n    return false;\n  }\n\n  /**\n   * Will call the subclass doTick implementation in this main loop tick\n   * or in the next one (via setTimeout(,0)) in case it has already been called\n   * in this tick (in case this is a re-entrant call).\n   */\n  public tick(): void {\n    this._tickCallCount++;\n    if (this._tickCallCount === 1) {\n      this.doTick();\n      // re-entrant call to tick from previous doTick call stack\n      // -> schedule a call on the next main loop iteration to process this task processing request\n      if (this._tickCallCount > 1) {\n        // make sure only one timer exists at any time at max\n        this.tickImmediate();\n      }\n      this._tickCallCount = 0;\n    }\n  }\n\n  public tickImmediate(): void {\n    this.clearNextTick();\n    this._tickTimer = self.setTimeout(this._boundTick, 0);\n  }\n\n  /**\n   * For subclass to implement task logic\n   * @abstract\n   */\n  protected doTick(): void {}\n}\n", "import { Events } from '../events';\nimport { Fragment, Part } from '../loader/fragment';\nimport { PlaylistLevelType } from '../types/loader';\nimport type { SourceBufferName } from '../types/buffer';\nimport type {\n  FragmentBufferedRange,\n  FragmentEntity,\n  FragmentTimeRange,\n} from '../types/fragment-tracker';\nimport type { ComponentAPI } from '../types/component-api';\nimport type {\n  BufferAppendedData,\n  FragBufferedData,\n  FragLoadedData,\n} from '../types/events';\nimport type Hls from '../hls';\n\nexport const enum FragmentState {\n  NOT_LOADED = 'NOT_LOADED',\n  APPENDING = 'APPENDING',\n  PARTIAL = 'PARTIAL',\n  OK = 'OK',\n}\n\nexport class FragmentTracker implements ComponentAPI {\n  private activePartLists: { [key in PlaylistLevelType]?: Part[] } =\n    Object.create(null);\n  private endListFragments: { [key in PlaylistLevelType]?: FragmentEntity } =\n    Object.create(null);\n  private fragments: Partial<Record<string, FragmentEntity>> =\n    Object.create(null);\n  private timeRanges:\n    | {\n        [key in SourceBufferName]?: TimeRanges;\n      }\n    | null = Object.create(null);\n\n  private bufferPadding: number = 0.2;\n  private hls: Hls;\n  private hasGaps: boolean = false;\n\n  constructor(hls: Hls) {\n    this.hls = hls;\n\n    this._registerListeners();\n  }\n\n  private _registerListeners() {\n    const { hls } = this;\n    hls.on(Events.BUFFER_APPENDED, this.onBufferAppended, this);\n    hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);\n    hls.on(Events.FRAG_LOADED, this.onFragLoaded, this);\n  }\n\n  private _unregisterListeners() {\n    const { hls } = this;\n    hls.off(Events.BUFFER_APPENDED, this.onBufferAppended, this);\n    hls.off(Events.FRAG_BUFFERED, this.onFragBuffered, this);\n    hls.off(Events.FRAG_LOADED, this.onFragLoaded, this);\n  }\n\n  public destroy() {\n    this._unregisterListeners();\n    // @ts-ignore\n    this.fragments =\n      // @ts-ignore\n      this.activePartLists =\n      // @ts-ignore\n      this.endListFragments =\n      this.timeRanges =\n        null;\n  }\n\n  /**\n   * Return a Fragment or Part with an appended range that matches the position and levelType\n   * Otherwise, return null\n   */\n  public getAppendedFrag(\n    position: number,\n    levelType: PlaylistLevelType,\n  ): Fragment | Part | null {\n    const activeParts = this.activePartLists[levelType];\n    if (activeParts) {\n      for (let i = activeParts.length; i--; ) {\n        const activePart = activeParts[i];\n        if (!activePart) {\n          break;\n        }\n        const appendedPTS = activePart.end;\n        if (\n          activePart.start <= position &&\n          appendedPTS !== null &&\n          position <= appendedPTS\n        ) {\n          return activePart;\n        }\n      }\n    }\n    return this.getBufferedFrag(position, levelType);\n  }\n\n  /**\n   * Return a buffered Fragment that matches the position and levelType.\n   * A buffered Fragment is one whose loading, parsing and appending is done (completed or \"partial\" meaning aborted).\n   * If not found any Fragment, return null\n   */\n  public getBufferedFrag(\n    position: number,\n    levelType: PlaylistLevelType,\n  ): Fragment | null {\n    const { fragments } = this;\n    const keys = Object.keys(fragments);\n    for (let i = keys.length; i--; ) {\n      const fragmentEntity = fragments[keys[i]];\n      if (fragmentEntity?.body.type === levelType && fragmentEntity.buffered) {\n        const frag = fragmentEntity.body;\n        if (frag.start <= position && position <= frag.end) {\n          return frag;\n        }\n      }\n    }\n    return null;\n  }\n\n  /**\n   * Partial fragments effected by coded frame eviction will be removed\n   * The browser will unload parts of the buffer to free up memory for new buffer data\n   * Fragments will need to be reloaded when the buffer is freed up, removing partial fragments will allow them to reload(since there might be parts that are still playable)\n   */\n  public detectEvictedFragments(\n    elementaryStream: SourceBufferName,\n    timeRange: TimeRanges,\n    playlistType: PlaylistLevelType,\n    appendedPart?: Part | null,\n  ) {\n    if (this.timeRanges) {\n      this.timeRanges[elementaryStream] = timeRange;\n    }\n    // Check if any flagged fragments have been unloaded\n    // excluding anything newer than appendedPartSn\n    const appendedPartSn = (appendedPart?.fragment.sn || -1) as number;\n    Object.keys(this.fragments).forEach((key) => {\n      const fragmentEntity = this.fragments[key];\n      if (!fragmentEntity) {\n        return;\n      }\n      if (appendedPartSn >= (fragmentEntity.body.sn as number)) {\n        return;\n      }\n      if (!fragmentEntity.buffered && !fragmentEntity.loaded) {\n        if (fragmentEntity.body.type === playlistType) {\n          this.removeFragment(fragmentEntity.body);\n        }\n        return;\n      }\n      const esData = fragmentEntity.range[elementaryStream];\n      if (!esData) {\n        return;\n      }\n      esData.time.some((time: FragmentTimeRange) => {\n        const isNotBuffered = !this.isTimeBuffered(\n          time.startPTS,\n          time.endPTS,\n          timeRange,\n        );\n        if (isNotBuffered) {\n          // Unregister partial fragment as it needs to load again to be reused\n          this.removeFragment(fragmentEntity.body);\n        }\n        return isNotBuffered;\n      });\n    });\n  }\n\n  /**\n   * Checks if the fragment passed in is loaded in the buffer properly\n   * Partially loaded fragments will be registered as a partial fragment\n   */\n  public detectPartialFragments(data: FragBufferedData) {\n    const timeRanges = this.timeRanges;\n    const { frag, part } = data;\n    if (!timeRanges || frag.sn === 'initSegment') {\n      return;\n    }\n\n    const fragKey = getFragmentKey(frag);\n    const fragmentEntity = this.fragments[fragKey];\n    if (!fragmentEntity || (fragmentEntity.buffered && frag.gap)) {\n      return;\n    }\n    const isFragHint = !frag.relurl;\n    Object.keys(timeRanges).forEach((elementaryStream: SourceBufferName) => {\n      const streamInfo = frag.elementaryStreams[elementaryStream];\n      if (!streamInfo) {\n        return;\n      }\n      const timeRange = timeRanges[elementaryStream] as TimeRanges;\n      const partial = isFragHint || streamInfo.partial === true;\n      fragmentEntity.range[elementaryStream] = this.getBufferedTimes(\n        frag,\n        part,\n        partial,\n        timeRange,\n      );\n    });\n    fragmentEntity.loaded = null;\n    if (Object.keys(fragmentEntity.range).length) {\n      fragmentEntity.buffered = true;\n      const endList = (fragmentEntity.body.endList =\n        frag.endList || fragmentEntity.body.endList);\n      if (endList) {\n        this.endListFragments[fragmentEntity.body.type] = fragmentEntity;\n      }\n      if (!isPartial(fragmentEntity)) {\n        // Remove older fragment parts from lookup after frag is tracked as buffered\n        this.removeParts((frag.sn as number) - 1, frag.type);\n      }\n    } else {\n      // remove fragment if nothing was appended\n      this.removeFragment(fragmentEntity.body);\n    }\n  }\n\n  private removeParts(snToKeep: number, levelType: PlaylistLevelType) {\n    const activeParts = this.activePartLists[levelType];\n    if (!activeParts) {\n      return;\n    }\n    this.activePartLists[levelType] = activeParts.filter(\n      (part) => (part.fragment.sn as number) >= snToKeep,\n    );\n  }\n\n  public fragBuffered(frag: Fragment, force?: true) {\n    const fragKey = getFragmentKey(frag);\n    let fragmentEntity = this.fragments[fragKey];\n    if (!fragmentEntity && force) {\n      fragmentEntity = this.fragments[fragKey] = {\n        body: frag,\n        appendedPTS: null,\n        loaded: null,\n        buffered: false,\n        range: Object.create(null),\n      };\n      if (frag.gap) {\n        this.hasGaps = true;\n      }\n    }\n    if (fragmentEntity) {\n      fragmentEntity.loaded = null;\n      fragmentEntity.buffered = true;\n    }\n  }\n\n  private getBufferedTimes(\n    fragment: Fragment,\n    part: Part | null,\n    partial: boolean,\n    timeRange: TimeRanges,\n  ): FragmentBufferedRange {\n    const buffered: FragmentBufferedRange = {\n      time: [],\n      partial,\n    };\n    const startPTS = fragment.start;\n    const endPTS = fragment.end;\n    const minEndPTS = fragment.minEndPTS || endPTS;\n    const maxStartPTS = fragment.maxStartPTS || startPTS;\n    for (let i = 0; i < timeRange.length; i++) {\n      const startTime = timeRange.start(i) - this.bufferPadding;\n      const endTime = timeRange.end(i) + this.bufferPadding;\n      if (maxStartPTS >= startTime && minEndPTS <= endTime) {\n        // Fragment is entirely contained in buffer\n        // No need to check the other timeRange times since it's completely playable\n        buffered.time.push({\n          startPTS: Math.max(startPTS, timeRange.start(i)),\n          endPTS: Math.min(endPTS, timeRange.end(i)),\n        });\n        break;\n      } else if (startPTS < endTime && endPTS > startTime) {\n        const start = Math.max(startPTS, timeRange.start(i));\n        const end = Math.min(endPTS, timeRange.end(i));\n        if (end > start) {\n          buffered.partial = true;\n          // Check for intersection with buffer\n          // Get playable sections of the fragment\n          buffered.time.push({\n            startPTS: start,\n            endPTS: end,\n          });\n        }\n      } else if (endPTS <= startTime) {\n        // No need to check the rest of the timeRange as it is in order\n        break;\n      }\n    }\n    return buffered;\n  }\n\n  /**\n   * Gets the partial fragment for a certain time\n   */\n  public getPartialFragment(time: number): Fragment | null {\n    let bestFragment: Fragment | null = null;\n    let timePadding: number;\n    let startTime: number;\n    let endTime: number;\n    let bestOverlap: number = 0;\n    const { bufferPadding, fragments } = this;\n    Object.keys(fragments).forEach((key) => {\n      const fragmentEntity = fragments[key];\n      if (!fragmentEntity) {\n        return;\n      }\n      if (isPartial(fragmentEntity)) {\n        startTime = fragmentEntity.body.start - bufferPadding;\n        endTime = fragmentEntity.body.end + bufferPadding;\n        if (time >= startTime && time <= endTime) {\n          // Use the fragment that has the most padding from start and end time\n          timePadding = Math.min(time - startTime, endTime - time);\n          if (bestOverlap <= timePadding) {\n            bestFragment = fragmentEntity.body;\n            bestOverlap = timePadding;\n          }\n        }\n      }\n    });\n    return bestFragment;\n  }\n\n  public isEndListAppended(type: PlaylistLevelType): boolean {\n    const lastFragmentEntity = this.endListFragments[type];\n    return (\n      lastFragmentEntity !== undefined &&\n      (lastFragmentEntity.buffered || isPartial(lastFragmentEntity))\n    );\n  }\n\n  public getState(fragment: Fragment): FragmentState {\n    const fragKey = getFragmentKey(fragment);\n    const fragmentEntity = this.fragments[fragKey];\n\n    if (fragmentEntity) {\n      if (!fragmentEntity.buffered) {\n        return FragmentState.APPENDING;\n      } else if (isPartial(fragmentEntity)) {\n        return FragmentState.PARTIAL;\n      } else {\n        return FragmentState.OK;\n      }\n    }\n\n    return FragmentState.NOT_LOADED;\n  }\n\n  private isTimeBuffered(\n    startPTS: number,\n    endPTS: number,\n    timeRange: TimeRanges,\n  ): boolean {\n    let startTime;\n    let endTime;\n    for (let i = 0; i < timeRange.length; i++) {\n      startTime = timeRange.start(i) - this.bufferPadding;\n      endTime = timeRange.end(i) + this.bufferPadding;\n      if (startPTS >= startTime && endPTS <= endTime) {\n        return true;\n      }\n\n      if (endPTS <= startTime) {\n        // No need to check the rest of the timeRange as it is in order\n        return false;\n      }\n    }\n\n    return false;\n  }\n\n  private onFragLoaded(event: Events.FRAG_LOADED, data: FragLoadedData) {\n    const { frag, part } = data;\n    // don't track initsegment (for which sn is not a number)\n    // don't track frags used for bitrateTest, they're irrelevant.\n    if (frag.sn === 'initSegment' || frag.bitrateTest) {\n      return;\n    }\n\n    // Fragment entity `loaded` FragLoadedData is null when loading parts\n    const loaded = part ? null : data;\n\n    const fragKey = getFragmentKey(frag);\n    this.fragments[fragKey] = {\n      body: frag,\n      appendedPTS: null,\n      loaded,\n      buffered: false,\n      range: Object.create(null),\n    };\n  }\n\n  private onBufferAppended(\n    event: Events.BUFFER_APPENDED,\n    data: BufferAppendedData,\n  ) {\n    const { frag, part, timeRanges } = data;\n    if (frag.sn === 'initSegment') {\n      return;\n    }\n    const playlistType = frag.type;\n    if (part) {\n      let activeParts = this.activePartLists[playlistType];\n      if (!activeParts) {\n        this.activePartLists[playlistType] = activeParts = [];\n      }\n      activeParts.push(part);\n    }\n    // Store the latest timeRanges loaded in the buffer\n    this.timeRanges = timeRanges;\n    Object.keys(timeRanges).forEach((elementaryStream: SourceBufferName) => {\n      const timeRange = timeRanges[elementaryStream] as TimeRanges;\n      this.detectEvictedFragments(\n        elementaryStream,\n        timeRange,\n        playlistType,\n        part,\n      );\n    });\n  }\n\n  private onFragBuffered(event: Events.FRAG_BUFFERED, data: FragBufferedData) {\n    this.detectPartialFragments(data);\n  }\n\n  private hasFragment(fragment: Fragment): boolean {\n    const fragKey = getFragmentKey(fragment);\n    return !!this.fragments[fragKey];\n  }\n\n  public hasParts(type: PlaylistLevelType): boolean {\n    return !!this.activePartLists[type]?.length;\n  }\n\n  public removeFragmentsInRange(\n    start: number,\n    end: number,\n    playlistType: PlaylistLevelType,\n    withGapOnly?: boolean,\n    unbufferedOnly?: boolean,\n  ) {\n    if (withGapOnly && !this.hasGaps) {\n      return;\n    }\n    Object.keys(this.fragments).forEach((key) => {\n      const fragmentEntity = this.fragments[key];\n      if (!fragmentEntity) {\n        return;\n      }\n      const frag = fragmentEntity.body;\n      if (frag.type !== playlistType || (withGapOnly && !frag.gap)) {\n        return;\n      }\n      if (\n        frag.start < end &&\n        frag.end > start &&\n        (fragmentEntity.buffered || unbufferedOnly)\n      ) {\n        this.removeFragment(frag);\n      }\n    });\n  }\n\n  public removeFragment(fragment: Fragment) {\n    const fragKey = getFragmentKey(fragment);\n    fragment.stats.loaded = 0;\n    fragment.clearElementaryStreamInfo();\n    const activeParts = this.activePartLists[fragment.type];\n    if (activeParts) {\n      const snToRemove = fragment.sn;\n      this.activePartLists[fragment.type] = activeParts.filter(\n        (part) => part.fragment.sn !== snToRemove,\n      );\n    }\n    delete this.fragments[fragKey];\n    if (fragment.endList) {\n      delete this.endListFragments[fragment.type];\n    }\n  }\n\n  public removeAllFragments() {\n    this.fragments = Object.create(null);\n    this.endListFragments = Object.create(null);\n    this.activePartLists = Object.create(null);\n    this.hasGaps = false;\n  }\n}\n\nfunction isPartial(fragmentEntity: FragmentEntity): boolean {\n  return (\n    fragmentEntity.buffered &&\n    (fragmentEntity.body.gap ||\n      fragmentEntity.range.video?.partial ||\n      fragmentEntity.range.audio?.partial ||\n      fragmentEntity.range.audiovideo?.partial)\n  );\n}\n\nfunction getFragmentKey(fragment: Fragment): string {\n  return `${fragment.type}_${fragment.level}_${fragment.sn}`;\n}\n", "/**\n * Provides methods dealing with buffer length retrieval for example.\n *\n * In general, a helper around HTML5 MediaElement TimeRanges gathered from `buffered` property.\n *\n * Also @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/buffered\n */\n\nimport { logger } from './logger';\n\ntype BufferTimeRange = {\n  start: number;\n  end: number;\n};\n\nexport type Bufferable = {\n  buffered: TimeRanges;\n};\n\nexport type BufferInfo = {\n  len: number;\n  start: number;\n  end: number;\n  nextStart?: number;\n};\n\nconst noopBuffered: TimeRanges = {\n  length: 0,\n  start: () => 0,\n  end: () => 0,\n};\n\nexport class BufferHelper {\n  /**\n   * Return true if `media`'s buffered include `position`\n   */\n  static isBuffered(media: Bufferable, position: number): boolean {\n    try {\n      if (media) {\n        const buffered = BufferHelper.getBuffered(media);\n        for (let i = 0; i < buffered.length; i++) {\n          if (position >= buffered.start(i) && position <= buffered.end(i)) {\n            return true;\n          }\n        }\n      }\n    } catch (error) {\n      // this is to catch\n      // InvalidStateError: Failed to read the 'buffered' property from 'SourceBuffer':\n      // This SourceBuffer has been removed from the parent media source\n    }\n    return false;\n  }\n\n  static bufferInfo(\n    media: Bufferable | null,\n    pos: number,\n    maxHoleDuration: number,\n  ): BufferInfo {\n    try {\n      if (media) {\n        const vbuffered = BufferHelper.getBuffered(media);\n        const buffered: BufferTimeRange[] = [];\n        let i: number;\n        for (i = 0; i < vbuffered.length; i++) {\n          buffered.push({ start: vbuffered.start(i), end: vbuffered.end(i) });\n        }\n\n        return this.bufferedInfo(buffered, pos, maxHoleDuration);\n      }\n    } catch (error) {\n      // this is to catch\n      // InvalidStateError: Failed to read the 'buffered' property from 'SourceBuffer':\n      // This SourceBuffer has been removed from the parent media source\n    }\n    return { len: 0, start: pos, end: pos, nextStart: undefined };\n  }\n\n  static bufferedInfo(\n    buffered: BufferTimeRange[],\n    pos: number,\n    maxHoleDuration: number,\n  ): {\n    len: number;\n    start: number;\n    end: number;\n    nextStart?: number;\n  } {\n    pos = Math.max(0, pos);\n    // sort on buffer.start/smaller end (IE does not always return sorted buffered range)\n    buffered.sort(function (a, b) {\n      const diff = a.start - b.start;\n      if (diff) {\n        return diff;\n      } else {\n        return b.end - a.end;\n      }\n    });\n\n    let buffered2: BufferTimeRange[] = [];\n    if (maxHoleDuration) {\n      // there might be some small holes between buffer time range\n      // consider that holes smaller than maxHoleDuration are irrelevant and build another\n      // buffer time range representations that discards those holes\n      for (let i = 0; i < buffered.length; i++) {\n        const buf2len = buffered2.length;\n        if (buf2len) {\n          const buf2end = buffered2[buf2len - 1].end;\n          // if small hole (value between 0 or maxHoleDuration ) or overlapping (negative)\n          if (buffered[i].start - buf2end < maxHoleDuration) {\n            // merge overlapping time ranges\n            // update lastRange.end only if smaller than item.end\n            // e.g.  [ 1, 15] with  [ 2,8] => [ 1,15] (no need to modify lastRange.end)\n            // whereas [ 1, 8] with  [ 2,15] => [ 1,15] ( lastRange should switch from [1,8] to [1,15])\n            if (buffered[i].end > buf2end) {\n              buffered2[buf2len - 1].end = buffered[i].end;\n            }\n          } else {\n            // big hole\n            buffered2.push(buffered[i]);\n          }\n        } else {\n          // first value\n          buffered2.push(buffered[i]);\n        }\n      }\n    } else {\n      buffered2 = buffered;\n    }\n\n    let bufferLen = 0;\n\n    // bufferStartNext can possibly be undefined based on the conditional logic below\n    let bufferStartNext: number | undefined;\n\n    // bufferStart and bufferEnd are buffer boundaries around current video position\n    let bufferStart: number = pos;\n    let bufferEnd: number = pos;\n    for (let i = 0; i < buffered2.length; i++) {\n      const start = buffered2[i].start;\n      const end = buffered2[i].end;\n      // logger.log('buf start/end:' + buffered.start(i) + '/' + buffered.end(i));\n      if (pos + maxHoleDuration >= start && pos < end) {\n        // play position is inside this buffer TimeRange, retrieve end of buffer position and buffer length\n        bufferStart = start;\n        bufferEnd = end;\n        bufferLen = bufferEnd - pos;\n      } else if (pos + maxHoleDuration < start) {\n        bufferStartNext = start;\n        break;\n      }\n    }\n    return {\n      len: bufferLen,\n      start: bufferStart || 0,\n      end: bufferEnd || 0,\n      nextStart: bufferStartNext,\n    };\n  }\n\n  /**\n   * Safe method to get buffered property.\n   * SourceBuffer.buffered may throw if SourceBuffer is removed from it's MediaSource\n   */\n  static getBuffered(media: Bufferable): TimeRanges {\n    try {\n      return media.buffered;\n    } catch (e) {\n      logger.log('failed to get media.buffered', e);\n      return noopBuffered;\n    }\n  }\n}\n", "import type { RemuxerResult } from './remuxer';\nimport type { HlsChunkPerformanceTiming } from './loader';\nimport type { SourceBufferName } from './buffer';\n\nexport interface TransmuxerResult {\n  remuxResult: RemuxerResult;\n  chunkMeta: ChunkMetadata;\n}\n\nexport class ChunkMetadata {\n  public readonly level: number;\n  public readonly sn: number;\n  public readonly part: number;\n  public readonly id: number;\n  public readonly size: number;\n  public readonly partial: boolean;\n  public readonly transmuxing: HlsChunkPerformanceTiming =\n    getNewPerformanceTiming();\n  public readonly buffering: {\n    [key in SourceBufferName]: HlsChunkPerformanceTiming;\n  } = {\n    audio: getNewPerformanceTiming(),\n    video: getNewPerformanceTiming(),\n    audiovideo: getNewPerformanceTiming(),\n  };\n\n  constructor(\n    level: number,\n    sn: number,\n    id: number,\n    size = 0,\n    part = -1,\n    partial = false,\n  ) {\n    this.level = level;\n    this.sn = sn;\n    this.id = id;\n    this.size = size;\n    this.part = part;\n    this.partial = partial;\n  }\n}\n\nfunction getNewPerformanceTiming(): HlsChunkPerformanceTiming {\n  return { start: 0, executeStart: 0, executeEnd: 0, end: 0 };\n}\n", "import { logger } from './logger';\nimport { adjustSliding } from './level-helper';\n\nimport type { Fragment } from '../loader/fragment';\nimport type { LevelDetails } from '../loader/level-details';\n\nexport function findFirstFragWithCC(\n  fragments: Fragment[],\n  cc: number,\n): Fragment | null {\n  for (let i = 0, len = fragments.length; i < len; i++) {\n    if (fragments[i]?.cc === cc) {\n      return fragments[i];\n    }\n  }\n  return null;\n}\n\nexport function shouldAlignOnDiscontinuities(\n  lastFrag: Fragment | null,\n  switchDetails: LevelDetails | undefined,\n  details: LevelDetails,\n): switchDetails is LevelDetails & boolean {\n  if (switchDetails) {\n    if (\n      details.endCC > details.startCC ||\n      (lastFrag && lastFrag.cc < details.startCC)\n    ) {\n      return true;\n    }\n  }\n  return false;\n}\n\n// Find the first frag in the previous level which matches the CC of the first frag of the new level\nexport function findDiscontinuousReferenceFrag(\n  prevDetails: LevelDetails,\n  curDetails: LevelDetails,\n) {\n  const prevFrags = prevDetails.fragments;\n  const curFrags = curDetails.fragments;\n\n  if (!curFrags.length || !prevFrags.length) {\n    logger.log('No fragments to align');\n    return;\n  }\n\n  const prevStartFrag = findFirstFragWithCC(prevFrags, curFrags[0].cc);\n\n  if (!prevStartFrag || (prevStartFrag && !prevStartFrag.startPTS)) {\n    logger.log('No frag in previous level to align on');\n    return;\n  }\n\n  return prevStartFrag;\n}\n\nfunction adjustFragmentStart(frag: Fragment, sliding: number) {\n  if (frag) {\n    const start = frag.start + sliding;\n    frag.start = frag.startPTS = start;\n    frag.endPTS = start + frag.duration;\n  }\n}\n\nexport function adjustSlidingStart(sliding: number, details: LevelDetails) {\n  // Update segments\n  const fragments = details.fragments;\n  for (let i = 0, len = fragments.length; i < len; i++) {\n    adjustFragmentStart(fragments[i], sliding);\n  }\n  // Update LL-HLS parts at the end of the playlist\n  if (details.fragmentHint) {\n    adjustFragmentStart(details.fragmentHint, sliding);\n  }\n  details.alignedSliding = true;\n}\n\n/**\n * Using the parameters of the last level, this function computes PTS' of the new fragments so that they form a\n * contiguous stream with the last fragments.\n * The PTS of a fragment lets Hls.js know where it fits into a stream - by knowing every PTS, we know which fragment to\n * download at any given time. PTS is normally computed when the fragment is demuxed, so taking this step saves us time\n * and an extra download.\n * @param lastFrag\n * @param lastLevel\n * @param details\n */\nexport function alignStream(\n  lastFrag: Fragment | null,\n  switchDetails: LevelDetails | undefined,\n  details: LevelDetails,\n) {\n  if (!switchDetails) {\n    return;\n  }\n  alignDiscontinuities(lastFrag, details, switchDetails);\n  if (!details.alignedSliding && switchDetails) {\n    // If the PTS wasn't figured out via discontinuity sequence that means there was no CC increase within the level.\n    // Aligning via Program Date Time should therefore be reliable, since PDT should be the same within the same\n    // discontinuity sequence.\n    alignMediaPlaylistByPDT(details, switchDetails);\n  }\n  if (!details.alignedSliding && switchDetails && !details.skippedSegments) {\n    // Try to align on sn so that we pick a better start fragment.\n    // Do not perform this on playlists with delta updates as this is only to align levels on switch\n    // and adjustSliding only adjusts fragments after skippedSegments.\n    adjustSliding(switchDetails, details);\n  }\n}\n\n/**\n * Computes the PTS if a new level's fragments using the PTS of a fragment in the last level which shares the same\n * discontinuity sequence.\n * @param lastFrag - The last Fragment which shares the same discontinuity sequence\n * @param lastLevel - The details of the last loaded level\n * @param details - The details of the new level\n */\nfunction alignDiscontinuities(\n  lastFrag: Fragment | null,\n  details: LevelDetails,\n  switchDetails: LevelDetails | undefined,\n) {\n  if (shouldAlignOnDiscontinuities(lastFrag, switchDetails, details)) {\n    const referenceFrag = findDiscontinuousReferenceFrag(\n      switchDetails,\n      details,\n    );\n    if (referenceFrag && Number.isFinite(referenceFrag.start)) {\n      logger.log(\n        `Adjusting PTS using last level due to CC increase within current level ${details.url}`,\n      );\n      adjustSlidingStart(referenceFrag.start, details);\n    }\n  }\n}\n\n/**\n * Ensures appropriate time-alignment between renditions based on PDT.\n * This function assumes the timelines represented in `refDetails` are accurate, including the PDTs\n * for the last discontinuity sequence number shared by both playlists when present,\n * and uses the \"wallclock\"/PDT timeline as a cross-reference to `details`, adjusting the presentation\n * times/timelines of `details` accordingly.\n * Given the asynchronous nature of fetches and initial loads of live `main` and audio/subtitle tracks,\n * the primary purpose of this function is to ensure the \"local timelines\" of audio/subtitle tracks\n * are aligned to the main/video timeline, using PDT as the cross-reference/\"anchor\" that should\n * be consistent across playlists, per the HLS spec.\n * @param details - The details of the rendition you'd like to time-align (e.g. an audio rendition).\n * @param refDetails - The details of the reference rendition with start and PDT times for alignment.\n */\nexport function alignMediaPlaylistByPDT(\n  details: LevelDetails,\n  refDetails: LevelDetails,\n) {\n  if (!details.hasProgramDateTime || !refDetails.hasProgramDateTime) {\n    return;\n  }\n\n  const fragments = details.fragments;\n  const refFragments = refDetails.fragments;\n  if (!fragments.length || !refFragments.length) {\n    return;\n  }\n\n  // Calculate a delta to apply to all fragments according to the delta in PDT times and start times\n  // of a fragment in the reference details, and a fragment in the target details of the same discontinuity.\n  // If a fragment of the same discontinuity was not found use the middle fragment of both.\n  let refFrag: Fragment | null | undefined;\n  let frag: Fragment | null | undefined;\n  const targetCC = Math.min(refDetails.endCC, details.endCC);\n  if (refDetails.startCC < targetCC && details.startCC < targetCC) {\n    refFrag = findFirstFragWithCC(refFragments, targetCC);\n    frag = findFirstFragWithCC(fragments, targetCC);\n  }\n  if (!refFrag || !frag) {\n    refFrag = refFragments[Math.floor(refFragments.length / 2)];\n    frag =\n      findFirstFragWithCC(fragments, refFrag.cc) ||\n      fragments[Math.floor(fragments.length / 2)];\n  }\n  const refPDT = refFrag.programDateTime;\n  const targetPDT = frag.programDateTime;\n  if (!refPDT || !targetPDT) {\n    return;\n  }\n\n  const delta = (targetPDT - refPDT) / 1000 - (frag.start - refFrag.start);\n  adjustSlidingStart(delta, details);\n}\n", "import { ErrorTypes, ErrorDetails } from '../errors';\nimport { Fragment } from './fragment';\nimport {\n  Loader,\n  LoaderConfiguration,\n  FragmentLoaderContext,\n} from '../types/loader';\nimport { getLoaderConfigWithoutReties } from '../utils/error-helper';\nimport type { HlsConfig } from '../config';\nimport type { BaseSegment, Part } from './fragment';\nimport type {\n  ErrorData,\n  FragLoadedData,\n  PartsLoadedData,\n} from '../types/events';\n\nconst MIN_CHUNK_SIZE = Math.pow(2, 17); // 128kb\n\nexport default class FragmentLoader {\n  private readonly config: HlsConfig;\n  private loader: Loader<FragmentLoaderContext> | null = null;\n  private partLoadTimeout: number = -1;\n\n  constructor(config: HlsConfig) {\n    this.config = config;\n  }\n\n  destroy() {\n    if (this.loader) {\n      this.loader.destroy();\n      this.loader = null;\n    }\n  }\n\n  abort() {\n    if (this.loader) {\n      // Abort the loader for current fragment. Only one may load at any given time\n      this.loader.abort();\n    }\n  }\n\n  load(\n    frag: Fragment,\n    onProgress?: FragmentLoadProgressCallback,\n  ): Promise<FragLoadedData> {\n    const url = frag.url;\n    if (!url) {\n      return Promise.reject(\n        new LoadError({\n          type: ErrorTypes.NETWORK_ERROR,\n          details: ErrorDetails.FRAG_LOAD_ERROR,\n          fatal: false,\n          frag,\n          error: new Error(\n            `Fragment does not have a ${url ? 'part list' : 'url'}`,\n          ),\n          networkDetails: null,\n        }),\n      );\n    }\n    this.abort();\n\n    const config = this.config;\n    const FragmentILoader = config.fLoader;\n    const DefaultILoader = config.loader;\n\n    return new Promise((resolve, reject) => {\n      if (this.loader) {\n        this.loader.destroy();\n      }\n      if (frag.gap) {\n        if (frag.tagList.some((tags) => tags[0] === 'GAP')) {\n          reject(createGapLoadError(frag));\n          return;\n        } else {\n          // Reset temporary treatment as GAP tag\n          frag.gap = false;\n        }\n      }\n      const loader =\n        (this.loader =\n        frag.loader =\n          FragmentILoader\n            ? new FragmentILoader(config)\n            : (new DefaultILoader(config) as Loader<FragmentLoaderContext>));\n      const loaderContext = createLoaderContext(frag);\n      const loadPolicy = getLoaderConfigWithoutReties(\n        config.fragLoadPolicy.default,\n      );\n      const loaderConfig: LoaderConfiguration = {\n        loadPolicy,\n        timeout: loadPolicy.maxLoadTimeMs,\n        maxRetry: 0,\n        retryDelay: 0,\n        maxRetryDelay: 0,\n        highWaterMark: frag.sn === 'initSegment' ? Infinity : MIN_CHUNK_SIZE,\n      };\n      // Assign frag stats to the loader's stats reference\n      frag.stats = loader.stats;\n      loader.load(loaderContext, loaderConfig, {\n        onSuccess: (response, stats, context, networkDetails) => {\n          this.resetLoader(frag, loader);\n          let payload = response.data as ArrayBuffer;\n          if (context.resetIV && frag.decryptdata) {\n            frag.decryptdata.iv = new Uint8Array(payload.slice(0, 16));\n            payload = payload.slice(16);\n          }\n          resolve({\n            frag,\n            part: null,\n            payload,\n            networkDetails,\n          });\n        },\n        onError: (response, context, networkDetails, stats) => {\n          this.resetLoader(frag, loader);\n          reject(\n            new LoadError({\n              type: ErrorTypes.NETWORK_ERROR,\n              details: ErrorDetails.FRAG_LOAD_ERROR,\n              fatal: false,\n              frag,\n              response: { url, data: undefined, ...response },\n              error: new Error(`HTTP Error ${response.code} ${response.text}`),\n              networkDetails,\n              stats,\n            }),\n          );\n        },\n        onAbort: (stats, context, networkDetails) => {\n          this.resetLoader(frag, loader);\n          reject(\n            new LoadError({\n              type: ErrorTypes.NETWORK_ERROR,\n              details: ErrorDetails.INTERNAL_ABORTED,\n              fatal: false,\n              frag,\n              error: new Error('Aborted'),\n              networkDetails,\n              stats,\n            }),\n          );\n        },\n        onTimeout: (stats, context, networkDetails) => {\n          this.resetLoader(frag, loader);\n          reject(\n            new LoadError({\n              type: ErrorTypes.NETWORK_ERROR,\n              details: ErrorDetails.FRAG_LOAD_TIMEOUT,\n              fatal: false,\n              frag,\n              error: new Error(`Timeout after ${loaderConfig.timeout}ms`),\n              networkDetails,\n              stats,\n            }),\n          );\n        },\n        onProgress: (stats, context, data, networkDetails) => {\n          if (onProgress) {\n            onProgress({\n              frag,\n              part: null,\n              payload: data as ArrayBuffer,\n              networkDetails,\n            });\n          }\n        },\n      });\n    });\n  }\n\n  public loadPart(\n    frag: Fragment,\n    part: Part,\n    onProgress: FragmentLoadProgressCallback,\n  ): Promise<FragLoadedData> {\n    this.abort();\n\n    const config = this.config;\n    const FragmentILoader = config.fLoader;\n    const DefaultILoader = config.loader;\n\n    return new Promise((resolve, reject) => {\n      if (this.loader) {\n        this.loader.destroy();\n      }\n      if (frag.gap || part.gap) {\n        reject(createGapLoadError(frag, part));\n        return;\n      }\n      const loader =\n        (this.loader =\n        frag.loader =\n          FragmentILoader\n            ? new FragmentILoader(config)\n            : (new DefaultILoader(config) as Loader<FragmentLoaderContext>));\n      const loaderContext = createLoaderContext(frag, part);\n      // Should we define another load policy for parts?\n      const loadPolicy = getLoaderConfigWithoutReties(\n        config.fragLoadPolicy.default,\n      );\n      const loaderConfig: LoaderConfiguration = {\n        loadPolicy,\n        timeout: loadPolicy.maxLoadTimeMs,\n        maxRetry: 0,\n        retryDelay: 0,\n        maxRetryDelay: 0,\n        highWaterMark: MIN_CHUNK_SIZE,\n      };\n      // Assign part stats to the loader's stats reference\n      part.stats = loader.stats;\n      loader.load(loaderContext, loaderConfig, {\n        onSuccess: (response, stats, context, networkDetails) => {\n          this.resetLoader(frag, loader);\n          this.updateStatsFromPart(frag, part);\n          const partLoadedData: FragLoadedData = {\n            frag,\n            part,\n            payload: response.data as ArrayBuffer,\n            networkDetails,\n          };\n          onProgress(partLoadedData);\n          resolve(partLoadedData);\n        },\n        onError: (response, context, networkDetails, stats) => {\n          this.resetLoader(frag, loader);\n          reject(\n            new LoadError({\n              type: ErrorTypes.NETWORK_ERROR,\n              details: ErrorDetails.FRAG_LOAD_ERROR,\n              fatal: false,\n              frag,\n              part,\n              response: {\n                url: loaderContext.url,\n                data: undefined,\n                ...response,\n              },\n              error: new Error(`HTTP Error ${response.code} ${response.text}`),\n              networkDetails,\n              stats,\n            }),\n          );\n        },\n        onAbort: (stats, context, networkDetails) => {\n          frag.stats.aborted = part.stats.aborted;\n          this.resetLoader(frag, loader);\n          reject(\n            new LoadError({\n              type: ErrorTypes.NETWORK_ERROR,\n              details: ErrorDetails.INTERNAL_ABORTED,\n              fatal: false,\n              frag,\n              part,\n              error: new Error('Aborted'),\n              networkDetails,\n              stats,\n            }),\n          );\n        },\n        onTimeout: (stats, context, networkDetails) => {\n          this.resetLoader(frag, loader);\n          reject(\n            new LoadError({\n              type: ErrorTypes.NETWORK_ERROR,\n              details: ErrorDetails.FRAG_LOAD_TIMEOUT,\n              fatal: false,\n              frag,\n              part,\n              error: new Error(`Timeout after ${loaderConfig.timeout}ms`),\n              networkDetails,\n              stats,\n            }),\n          );\n        },\n      });\n    });\n  }\n\n  private updateStatsFromPart(frag: Fragment, part: Part) {\n    const fragStats = frag.stats;\n    const partStats = part.stats;\n    const partTotal = partStats.total;\n    fragStats.loaded += partStats.loaded;\n    if (partTotal) {\n      const estTotalParts = Math.round(frag.duration / part.duration);\n      const estLoadedParts = Math.min(\n        Math.round(fragStats.loaded / partTotal),\n        estTotalParts,\n      );\n      const estRemainingParts = estTotalParts - estLoadedParts;\n      const estRemainingBytes =\n        estRemainingParts * Math.round(fragStats.loaded / estLoadedParts);\n      fragStats.total = fragStats.loaded + estRemainingBytes;\n    } else {\n      fragStats.total = Math.max(fragStats.loaded, fragStats.total);\n    }\n    const fragLoading = fragStats.loading;\n    const partLoading = partStats.loading;\n    if (fragLoading.start) {\n      // add to fragment loader latency\n      fragLoading.first += partLoading.first - partLoading.start;\n    } else {\n      fragLoading.start = partLoading.start;\n      fragLoading.first = partLoading.first;\n    }\n    fragLoading.end = partLoading.end;\n  }\n\n  private resetLoader(frag: Fragment, loader: Loader<FragmentLoaderContext>) {\n    frag.loader = null;\n    if (this.loader === loader) {\n      self.clearTimeout(this.partLoadTimeout);\n      this.loader = null;\n    }\n    loader.destroy();\n  }\n}\n\nfunction createLoaderContext(\n  frag: Fragment,\n  part: Part | null = null,\n): FragmentLoaderContext {\n  const segment: BaseSegment = part || frag;\n  const loaderContext: FragmentLoaderContext = {\n    frag,\n    part,\n    responseType: 'arraybuffer',\n    url: segment.url,\n    headers: {},\n    rangeStart: 0,\n    rangeEnd: 0,\n  };\n  const start = segment.byteRangeStartOffset as number;\n  const end = segment.byteRangeEndOffset as number;\n  if (Number.isFinite(start) && Number.isFinite(end)) {\n    let byteRangeStart = start;\n    let byteRangeEnd = end;\n    if (frag.sn === 'initSegment' && frag.decryptdata?.method === 'AES-128') {\n      // MAP segment encrypted with method 'AES-128', when served with HTTP Range,\n      // has the unencrypted size specified in the range.\n      // Ref: https://tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08#section-6.3.6\n      const fragmentLen = end - start;\n      if (fragmentLen % 16) {\n        byteRangeEnd = end + (16 - (fragmentLen % 16));\n      }\n      if (start !== 0) {\n        loaderContext.resetIV = true;\n        byteRangeStart = start - 16;\n      }\n    }\n    loaderContext.rangeStart = byteRangeStart;\n    loaderContext.rangeEnd = byteRangeEnd;\n  }\n  return loaderContext;\n}\n\nfunction createGapLoadError(frag: Fragment, part?: Part): LoadError {\n  const error = new Error(`GAP ${frag.gap ? 'tag' : 'attribute'} found`);\n  const errorData: FragLoadFailResult = {\n    type: ErrorTypes.MEDIA_ERROR,\n    details: ErrorDetails.FRAG_GAP,\n    fatal: false,\n    frag,\n    error,\n    networkDetails: null,\n  };\n  if (part) {\n    errorData.part = part;\n  }\n  (part ? part : frag).stats.aborted = true;\n  return new LoadError(errorData);\n}\n\nexport class LoadError extends Error {\n  public readonly data: FragLoadFailResult;\n  constructor(data: FragLoadFailResult) {\n    super(data.error.message);\n    this.data = data;\n  }\n}\n\nexport interface FragLoadFailResult extends ErrorData {\n  frag: Fragment;\n  part?: Part;\n  response?: {\n    data: any;\n    // error status code\n    code: number;\n    // error description\n    text: string;\n    url: string;\n  };\n  networkDetails: any;\n}\n\nexport type FragmentLoadProgressCallback = (\n  result: FragLoadedData | PartsLoadedData,\n) => void;\n", "export default class AESCrypto {\n  private subtle: SubtleCrypto;\n  private aesIV: Uint8Array;\n\n  constructor(subtle: SubtleCrypto, iv: Uint8Array) {\n    this.subtle = subtle;\n    this.aesIV = iv;\n  }\n\n  decrypt(data: ArrayBuffer, key: CryptoKey) {\n    return this.subtle.decrypt({ name: 'AES-CBC', iv: this.aesIV }, key, data);\n  }\n}\n", "export default class FastAESKey {\n  private subtle: SubtleCrypto;\n  private key: ArrayBuffer;\n\n  constructor(subtle: SubtleCrypto, key: ArrayBuffer) {\n    this.subtle = subtle;\n    this.key = key;\n  }\n\n  expandKey() {\n    return this.subtle.importKey('raw', this.key, { name: 'AES-CBC' }, false, [\n      'encrypt',\n      'decrypt',\n    ]);\n  }\n}\n", "import { sliceUint8 } from '../utils/typed-array';\n\n// PKCS7\nexport function removePadding(array: Uint8Array): Uint8Array {\n  const outputBytes = array.byteLength;\n  const paddingBytes =\n    outputBytes && new DataView(array.buffer).getUint8(outputBytes - 1);\n  if (paddingBytes) {\n    return sliceUint8(array, 0, outputBytes - paddingBytes);\n  }\n  return array;\n}\n\nexport default class AESDecryptor {\n  private rcon: Array<number> = [\n    0x0, 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36,\n  ];\n  private subMix: Array<Uint32Array> = [\n    new Uint32Array(256),\n    new Uint32Array(256),\n    new Uint32Array(256),\n    new Uint32Array(256),\n  ];\n  private invSubMix: Array<Uint32Array> = [\n    new Uint32Array(256),\n    new Uint32Array(256),\n    new Uint32Array(256),\n    new Uint32Array(256),\n  ];\n  private sBox: Uint32Array = new Uint32Array(256);\n  private invSBox: Uint32Array = new Uint32Array(256);\n  private key: Uint32Array = new Uint32Array(0);\n\n  private ksRows: number = 0;\n  private keySize: number = 0;\n  private keySchedule!: Uint32Array;\n  private invKeySchedule!: Uint32Array;\n\n  constructor() {\n    this.initTable();\n  }\n\n  // Using view.getUint32() also swaps the byte order.\n  uint8ArrayToUint32Array_(arrayBuffer) {\n    const view = new DataView(arrayBuffer);\n    const newArray = new Uint32Array(4);\n    for (let i = 0; i < 4; i++) {\n      newArray[i] = view.getUint32(i * 4);\n    }\n\n    return newArray;\n  }\n\n  initTable() {\n    const sBox = this.sBox;\n    const invSBox = this.invSBox;\n    const subMix = this.subMix;\n    const subMix0 = subMix[0];\n    const subMix1 = subMix[1];\n    const subMix2 = subMix[2];\n    const subMix3 = subMix[3];\n    const invSubMix = this.invSubMix;\n    const invSubMix0 = invSubMix[0];\n    const invSubMix1 = invSubMix[1];\n    const invSubMix2 = invSubMix[2];\n    const invSubMix3 = invSubMix[3];\n\n    const d = new Uint32Array(256);\n    let x = 0;\n    let xi = 0;\n    let i = 0;\n    for (i = 0; i < 256; i++) {\n      if (i < 128) {\n        d[i] = i << 1;\n      } else {\n        d[i] = (i << 1) ^ 0x11b;\n      }\n    }\n\n    for (i = 0; i < 256; i++) {\n      let sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4);\n      sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63;\n      sBox[x] = sx;\n      invSBox[sx] = x;\n\n      // Compute multiplication\n      const x2 = d[x];\n      const x4 = d[x2];\n      const x8 = d[x4];\n\n      // Compute sub/invSub bytes, mix columns tables\n      let t = (d[sx] * 0x101) ^ (sx * 0x1010100);\n      subMix0[x] = (t << 24) | (t >>> 8);\n      subMix1[x] = (t << 16) | (t >>> 16);\n      subMix2[x] = (t << 8) | (t >>> 24);\n      subMix3[x] = t;\n\n      // Compute inv sub bytes, inv mix columns tables\n      t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100);\n      invSubMix0[sx] = (t << 24) | (t >>> 8);\n      invSubMix1[sx] = (t << 16) | (t >>> 16);\n      invSubMix2[sx] = (t << 8) | (t >>> 24);\n      invSubMix3[sx] = t;\n\n      // Compute next counter\n      if (!x) {\n        x = xi = 1;\n      } else {\n        x = x2 ^ d[d[d[x8 ^ x2]]];\n        xi ^= d[d[xi]];\n      }\n    }\n  }\n\n  expandKey(keyBuffer: ArrayBuffer) {\n    // convert keyBuffer to Uint32Array\n    const key = this.uint8ArrayToUint32Array_(keyBuffer);\n    let sameKey = true;\n    let offset = 0;\n\n    while (offset < key.length && sameKey) {\n      sameKey = key[offset] === this.key[offset];\n      offset++;\n    }\n\n    if (sameKey) {\n      return;\n    }\n\n    this.key = key;\n    const keySize = (this.keySize = key.length);\n\n    if (keySize !== 4 && keySize !== 6 && keySize !== 8) {\n      throw new Error('Invalid aes key size=' + keySize);\n    }\n\n    const ksRows = (this.ksRows = (keySize + 6 + 1) * 4);\n    let ksRow;\n    let invKsRow;\n\n    const keySchedule = (this.keySchedule = new Uint32Array(ksRows));\n    const invKeySchedule = (this.invKeySchedule = new Uint32Array(ksRows));\n    const sbox = this.sBox;\n    const rcon = this.rcon;\n\n    const invSubMix = this.invSubMix;\n    const invSubMix0 = invSubMix[0];\n    const invSubMix1 = invSubMix[1];\n    const invSubMix2 = invSubMix[2];\n    const invSubMix3 = invSubMix[3];\n\n    let prev;\n    let t;\n\n    for (ksRow = 0; ksRow < ksRows; ksRow++) {\n      if (ksRow < keySize) {\n        prev = keySchedule[ksRow] = key[ksRow];\n        continue;\n      }\n      t = prev;\n\n      if (ksRow % keySize === 0) {\n        // Rot word\n        t = (t << 8) | (t >>> 24);\n\n        // Sub word\n        t =\n          (sbox[t >>> 24] << 24) |\n          (sbox[(t >>> 16) & 0xff] << 16) |\n          (sbox[(t >>> 8) & 0xff] << 8) |\n          sbox[t & 0xff];\n\n        // Mix Rcon\n        t ^= rcon[(ksRow / keySize) | 0] << 24;\n      } else if (keySize > 6 && ksRow % keySize === 4) {\n        // Sub word\n        t =\n          (sbox[t >>> 24] << 24) |\n          (sbox[(t >>> 16) & 0xff] << 16) |\n          (sbox[(t >>> 8) & 0xff] << 8) |\n          sbox[t & 0xff];\n      }\n\n      keySchedule[ksRow] = prev = (keySchedule[ksRow - keySize] ^ t) >>> 0;\n    }\n\n    for (invKsRow = 0; invKsRow < ksRows; invKsRow++) {\n      ksRow = ksRows - invKsRow;\n      if (invKsRow & 3) {\n        t = keySchedule[ksRow];\n      } else {\n        t = keySchedule[ksRow - 4];\n      }\n\n      if (invKsRow < 4 || ksRow <= 4) {\n        invKeySchedule[invKsRow] = t;\n      } else {\n        invKeySchedule[invKsRow] =\n          invSubMix0[sbox[t >>> 24]] ^\n          invSubMix1[sbox[(t >>> 16) & 0xff]] ^\n          invSubMix2[sbox[(t >>> 8) & 0xff]] ^\n          invSubMix3[sbox[t & 0xff]];\n      }\n\n      invKeySchedule[invKsRow] = invKeySchedule[invKsRow] >>> 0;\n    }\n  }\n\n  // Adding this as a method greatly improves performance.\n  networkToHostOrderSwap(word) {\n    return (\n      (word << 24) |\n      ((word & 0xff00) << 8) |\n      ((word & 0xff0000) >> 8) |\n      (word >>> 24)\n    );\n  }\n\n  decrypt(inputArrayBuffer: ArrayBuffer, offset: number, aesIV: ArrayBuffer) {\n    const nRounds = this.keySize + 6;\n    const invKeySchedule = this.invKeySchedule;\n    const invSBOX = this.invSBox;\n\n    const invSubMix = this.invSubMix;\n    const invSubMix0 = invSubMix[0];\n    const invSubMix1 = invSubMix[1];\n    const invSubMix2 = invSubMix[2];\n    const invSubMix3 = invSubMix[3];\n\n    const initVector = this.uint8ArrayToUint32Array_(aesIV);\n    let initVector0 = initVector[0];\n    let initVector1 = initVector[1];\n    let initVector2 = initVector[2];\n    let initVector3 = initVector[3];\n\n    const inputInt32 = new Int32Array(inputArrayBuffer);\n    const outputInt32 = new Int32Array(inputInt32.length);\n\n    let t0, t1, t2, t3;\n    let s0, s1, s2, s3;\n    let inputWords0, inputWords1, inputWords2, inputWords3;\n\n    let ksRow, i;\n    const swapWord = this.networkToHostOrderSwap;\n\n    while (offset < inputInt32.length) {\n      inputWords0 = swapWord(inputInt32[offset]);\n      inputWords1 = swapWord(inputInt32[offset + 1]);\n      inputWords2 = swapWord(inputInt32[offset + 2]);\n      inputWords3 = swapWord(inputInt32[offset + 3]);\n\n      s0 = inputWords0 ^ invKeySchedule[0];\n      s1 = inputWords3 ^ invKeySchedule[1];\n      s2 = inputWords2 ^ invKeySchedule[2];\n      s3 = inputWords1 ^ invKeySchedule[3];\n\n      ksRow = 4;\n\n      // Iterate through the rounds of decryption\n      for (i = 1; i < nRounds; i++) {\n        t0 =\n          invSubMix0[s0 >>> 24] ^\n          invSubMix1[(s1 >> 16) & 0xff] ^\n          invSubMix2[(s2 >> 8) & 0xff] ^\n          invSubMix3[s3 & 0xff] ^\n          invKeySchedule[ksRow];\n        t1 =\n          invSubMix0[s1 >>> 24] ^\n          invSubMix1[(s2 >> 16) & 0xff] ^\n          invSubMix2[(s3 >> 8) & 0xff] ^\n          invSubMix3[s0 & 0xff] ^\n          invKeySchedule[ksRow + 1];\n        t2 =\n          invSubMix0[s2 >>> 24] ^\n          invSubMix1[(s3 >> 16) & 0xff] ^\n          invSubMix2[(s0 >> 8) & 0xff] ^\n          invSubMix3[s1 & 0xff] ^\n          invKeySchedule[ksRow + 2];\n        t3 =\n          invSubMix0[s3 >>> 24] ^\n          invSubMix1[(s0 >> 16) & 0xff] ^\n          invSubMix2[(s1 >> 8) & 0xff] ^\n          invSubMix3[s2 & 0xff] ^\n          invKeySchedule[ksRow + 3];\n        // Update state\n        s0 = t0;\n        s1 = t1;\n        s2 = t2;\n        s3 = t3;\n\n        ksRow = ksRow + 4;\n      }\n\n      // Shift rows, sub bytes, add round key\n      t0 =\n        (invSBOX[s0 >>> 24] << 24) ^\n        (invSBOX[(s1 >> 16) & 0xff] << 16) ^\n        (invSBOX[(s2 >> 8) & 0xff] << 8) ^\n        invSBOX[s3 & 0xff] ^\n        invKeySchedule[ksRow];\n      t1 =\n        (invSBOX[s1 >>> 24] << 24) ^\n        (invSBOX[(s2 >> 16) & 0xff] << 16) ^\n        (invSBOX[(s3 >> 8) & 0xff] << 8) ^\n        invSBOX[s0 & 0xff] ^\n        invKeySchedule[ksRow + 1];\n      t2 =\n        (invSBOX[s2 >>> 24] << 24) ^\n        (invSBOX[(s3 >> 16) & 0xff] << 16) ^\n        (invSBOX[(s0 >> 8) & 0xff] << 8) ^\n        invSBOX[s1 & 0xff] ^\n        invKeySchedule[ksRow + 2];\n      t3 =\n        (invSBOX[s3 >>> 24] << 24) ^\n        (invSBOX[(s0 >> 16) & 0xff] << 16) ^\n        (invSBOX[(s1 >> 8) & 0xff] << 8) ^\n        invSBOX[s2 & 0xff] ^\n        invKeySchedule[ksRow + 3];\n\n      // Write\n      outputInt32[offset] = swapWord(t0 ^ initVector0);\n      outputInt32[offset + 1] = swapWord(t3 ^ initVector1);\n      outputInt32[offset + 2] = swapWord(t2 ^ initVector2);\n      outputInt32[offset + 3] = swapWord(t1 ^ initVector3);\n\n      // reset initVector to last 4 unsigned int\n      initVector0 = inputWords0;\n      initVector1 = inputWords1;\n      initVector2 = inputWords2;\n      initVector3 = inputWords3;\n\n      offset = offset + 4;\n    }\n\n    return outputInt32.buffer;\n  }\n}\n", "import AESCrypto from './aes-crypto';\nimport FastAESKey from './fast-aes-key';\nimport AESDecryptor, { removePadding } from './aes-decryptor';\nimport { logger } from '../utils/logger';\nimport { appendUint8Array } from '../utils/mp4-tools';\nimport { sliceUint8 } from '../utils/typed-array';\nimport type { HlsConfig } from '../config';\n\nconst CHUNK_SIZE = 16; // 16 bytes, 128 bits\n\nexport default class Decrypter {\n  private logEnabled: boolean = true;\n  private removePKCS7Padding: boolean;\n  private subtle: SubtleCrypto | null = null;\n  private softwareDecrypter: AESDecryptor | null = null;\n  private key: ArrayBuffer | null = null;\n  private fastAesKey: FastAESKey | null = null;\n  private remainderData: Uint8Array | null = null;\n  private currentIV: ArrayBuffer | null = null;\n  private currentResult: ArrayBuffer | null = null;\n  private useSoftware: boolean;\n\n  constructor(config: HlsConfig, { removePKCS7Padding = true } = {}) {\n    this.useSoftware = config.enableSoftwareAES;\n    this.removePKCS7Padding = removePKCS7Padding;\n    // built in decryptor expects PKCS7 padding\n    if (removePKCS7Padding) {\n      try {\n        const browserCrypto = self.crypto;\n        if (browserCrypto) {\n          this.subtle =\n            browserCrypto.subtle ||\n            ((browserCrypto as any).webkitSubtle as SubtleCrypto);\n        }\n      } catch (e) {\n        /* no-op */\n      }\n    }\n\n    this.useSoftware = !this.subtle;\n  }\n\n  destroy() {\n    this.subtle = null;\n    this.softwareDecrypter = null;\n    this.key = null;\n    this.fastAesKey = null;\n    this.remainderData = null;\n    this.currentIV = null;\n    this.currentResult = null;\n  }\n\n  public isSync() {\n    return this.useSoftware;\n  }\n\n  public flush(): Uint8Array | null {\n    const { currentResult, remainderData } = this;\n    if (!currentResult || remainderData) {\n      this.reset();\n      return null;\n    }\n    const data = new Uint8Array(currentResult);\n    this.reset();\n    if (this.removePKCS7Padding) {\n      return removePadding(data);\n    }\n    return data;\n  }\n\n  public reset() {\n    this.currentResult = null;\n    this.currentIV = null;\n    this.remainderData = null;\n    if (this.softwareDecrypter) {\n      this.softwareDecrypter = null;\n    }\n  }\n\n  public decrypt(\n    data: Uint8Array | ArrayBuffer,\n    key: ArrayBuffer,\n    iv: ArrayBuffer,\n  ): Promise<ArrayBuffer> {\n    if (this.useSoftware) {\n      return new Promise((resolve, reject) => {\n        this.softwareDecrypt(new Uint8Array(data), key, iv);\n        const decryptResult = this.flush();\n        if (decryptResult) {\n          resolve(decryptResult.buffer);\n        } else {\n          reject(new Error('[softwareDecrypt] Failed to decrypt data'));\n        }\n      });\n    }\n    return this.webCryptoDecrypt(new Uint8Array(data), key, iv);\n  }\n\n  // Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached\n  // data is handled in the flush() call\n  public softwareDecrypt(\n    data: Uint8Array,\n    key: ArrayBuffer,\n    iv: ArrayBuffer,\n  ): ArrayBuffer | null {\n    const { currentIV, currentResult, remainderData } = this;\n    this.logOnce('JS AES decrypt');\n    // The output is staggered during progressive parsing - the current result is cached, and emitted on the next call\n    // This is done in order to strip PKCS7 padding, which is found at the end of each segment. We only know we've reached\n    // the end on flush(), but by that time we have already received all bytes for the segment.\n    // Progressive decryption does not work with WebCrypto\n\n    if (remainderData) {\n      data = appendUint8Array(remainderData, data);\n      this.remainderData = null;\n    }\n\n    // Byte length must be a multiple of 16 (AES-128 = 128 bit blocks = 16 bytes)\n    const currentChunk = this.getValidChunk(data);\n    if (!currentChunk.length) {\n      return null;\n    }\n\n    if (currentIV) {\n      iv = currentIV;\n    }\n\n    let softwareDecrypter = this.softwareDecrypter;\n    if (!softwareDecrypter) {\n      softwareDecrypter = this.softwareDecrypter = new AESDecryptor();\n    }\n    softwareDecrypter.expandKey(key);\n\n    const result = currentResult;\n\n    this.currentResult = softwareDecrypter.decrypt(currentChunk.buffer, 0, iv);\n    this.currentIV = sliceUint8(currentChunk, -16).buffer;\n\n    if (!result) {\n      return null;\n    }\n    return result;\n  }\n\n  public webCryptoDecrypt(\n    data: Uint8Array,\n    key: ArrayBuffer,\n    iv: ArrayBuffer,\n  ): Promise<ArrayBuffer> {\n    if (this.key !== key || !this.fastAesKey) {\n      if (!this.subtle) {\n        return Promise.resolve(this.onWebCryptoError(data, key, iv));\n      }\n      this.key = key;\n      this.fastAesKey = new FastAESKey(this.subtle, key);\n    }\n    return this.fastAesKey\n      .expandKey()\n      .then((aesKey) => {\n        // decrypt using web crypto\n        if (!this.subtle) {\n          return Promise.reject(new Error('web crypto not initialized'));\n        }\n        this.logOnce('WebCrypto AES decrypt');\n        const crypto = new AESCrypto(this.subtle, new Uint8Array(iv));\n        return crypto.decrypt(data.buffer, aesKey);\n      })\n      .catch((err) => {\n        logger.warn(\n          `[decrypter]: WebCrypto Error, disable WebCrypto API, ${err.name}: ${err.message}`,\n        );\n\n        return this.onWebCryptoError(data, key, iv);\n      });\n  }\n\n  private onWebCryptoError(\n    data: Uint8Array,\n    key: ArrayBuffer,\n    iv: ArrayBuffer,\n  ): ArrayBuffer | never {\n    this.useSoftware = true;\n    this.logEnabled = true;\n    this.softwareDecrypt(data, key, iv);\n    const decryptResult = this.flush();\n    if (decryptResult) {\n      return decryptResult.buffer;\n    }\n    throw new Error('WebCrypto and softwareDecrypt: failed to decrypt data');\n  }\n\n  private getValidChunk(data: Uint8Array): Uint8Array {\n    let currentChunk = data;\n    const splitPoint = data.length - (data.length % CHUNK_SIZE);\n    if (splitPoint !== data.length) {\n      currentChunk = sliceUint8(data, 0, splitPoint);\n      this.remainderData = sliceUint8(data, splitPoint);\n    }\n    return currentChunk;\n  }\n\n  private logOnce(msg: string) {\n    if (!this.logEnabled) {\n      return;\n    }\n    logger.log(`[decrypter]: ${msg}`);\n    this.logEnabled = false;\n  }\n}\n", "/**\n *  TimeRanges to string helper\n */\n\nconst TimeRanges = {\n  toString: function (r: TimeRanges) {\n    let log = '';\n    const len = r.length;\n    for (let i = 0; i < len; i++) {\n      log += `[${r.start(i).toFixed(3)}-${r.end(i).toFixed(3)}]`;\n    }\n\n    return log;\n  },\n};\n\nexport default TimeRanges;\n", "import TaskLoop from '../task-loop';\nimport { FragmentState } from './fragment-tracker';\nimport { Bufferable, BufferHelper, BufferInfo } from '../utils/buffer-helper';\nimport { logger } from '../utils/logger';\nimport { Events } from '../events';\nimport { ErrorDetails, ErrorTypes } from '../errors';\nimport { ChunkMetadata } from '../types/transmuxer';\nimport { appendUint8Array } from '../utils/mp4-tools';\nimport { alignStream } from '../utils/discontinuities';\nimport {\n  findFragmentByPDT,\n  findFragmentByPTS,\n  findFragWithCC,\n} from './fragment-finders';\nimport {\n  findPart,\n  getFragmentWithSN,\n  getPartWith,\n  updateFragPTSDTS,\n} from '../utils/level-helper';\nimport TransmuxerInterface from '../demux/transmuxer-interface';\nimport { Fragment, Part } from '../loader/fragment';\nimport FragmentLoader, {\n  FragmentLoadProgressCallback,\n  LoadError,\n} from '../loader/fragment-loader';\nimport KeyLoader from '../loader/key-loader';\nimport { LevelDetails } from '../loader/level-details';\nimport Decrypter from '../crypt/decrypter';\nimport TimeRanges from '../utils/time-ranges';\nimport { PlaylistLevelType } from '../types/loader';\nimport { getRetryDelay } from '../utils/error-helper';\nimport { NetworkErrorAction } from './error-controller';\nimport type {\n  BufferAppendingData,\n  ErrorData,\n  FragLoadedData,\n  PartsLoadedData,\n  KeyLoadedData,\n  MediaAttachedData,\n  BufferFlushingData,\n  ManifestLoadedData,\n} from '../types/events';\nimport type { FragmentTracker } from './fragment-tracker';\nimport type { Level } from '../types/level';\nimport type { RemuxedTrack } from '../types/remuxer';\nimport type Hls from '../hls';\nimport type { HlsConfig } from '../config';\nimport type { NetworkComponentAPI } from '../types/component-api';\nimport type { SourceBufferName } from '../types/buffer';\nimport type { RationalTimestamp } from '../utils/timescale-conversion';\n\ntype ResolveFragLoaded = (FragLoadedEndData) => void;\ntype RejectFragLoaded = (LoadError) => void;\n\nexport const State = {\n  STOPPED: 'STOPPED',\n  IDLE: 'IDLE',\n  KEY_LOADING: 'KEY_LOADING',\n  FRAG_LOADING: 'FRAG_LOADING',\n  FRAG_LOADING_WAITING_RETRY: 'FRAG_LOADING_WAITING_RETRY',\n  WAITING_TRACK: 'WAITING_TRACK',\n  PARSING: 'PARSING',\n  PARSED: 'PARSED',\n  ENDED: 'ENDED',\n  ERROR: 'ERROR',\n  WAITING_INIT_PTS: 'WAITING_INIT_PTS',\n  WAITING_LEVEL: 'WAITING_LEVEL',\n};\n\nexport default class BaseStreamController\n  extends TaskLoop\n  implements NetworkComponentAPI\n{\n  protected hls: Hls;\n\n  protected fragPrevious: Fragment | null = null;\n  protected fragCurrent: Fragment | null = null;\n  protected fragmentTracker: FragmentTracker;\n  protected transmuxer: TransmuxerInterface | null = null;\n  protected _state: string = State.STOPPED;\n  protected playlistType: PlaylistLevelType;\n  protected media: HTMLMediaElement | null = null;\n  protected mediaBuffer: Bufferable | null = null;\n  protected config: HlsConfig;\n  protected bitrateTest: boolean = false;\n  protected lastCurrentTime: number = 0;\n  protected nextLoadPosition: number = 0;\n  protected startPosition: number = 0;\n  protected startTimeOffset: number | null = null;\n  protected loadedmetadata: boolean = false;\n  protected retryDate: number = 0;\n  protected levels: Array<Level> | null = null;\n  protected fragmentLoader: FragmentLoader;\n  protected keyLoader: KeyLoader;\n  protected levelLastLoaded: Level | null = null;\n  protected startFragRequested: boolean = false;\n  protected decrypter: Decrypter;\n  protected initPTS: RationalTimestamp[] = [];\n  protected onvseeking: EventListener | null = null;\n  protected onvended: EventListener | null = null;\n\n  private readonly logPrefix: string = '';\n  protected log: (msg: any) => void;\n  protected warn: (msg: any) => void;\n\n  constructor(\n    hls: Hls,\n    fragmentTracker: FragmentTracker,\n    keyLoader: KeyLoader,\n    logPrefix: string,\n    playlistType: PlaylistLevelType,\n  ) {\n    super();\n    this.playlistType = playlistType;\n    this.logPrefix = logPrefix;\n    this.log = logger.log.bind(logger, `${logPrefix}:`);\n    this.warn = logger.warn.bind(logger, `${logPrefix}:`);\n    this.hls = hls;\n    this.fragmentLoader = new FragmentLoader(hls.config);\n    this.keyLoader = keyLoader;\n    this.fragmentTracker = fragmentTracker;\n    this.config = hls.config;\n    this.decrypter = new Decrypter(hls.config);\n    hls.on(Events.MANIFEST_LOADED, this.onManifestLoaded, this);\n  }\n\n  protected doTick() {\n    this.onTickEnd();\n  }\n\n  protected onTickEnd() {}\n\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  public startLoad(startPosition: number): void {}\n\n  public stopLoad() {\n    this.fragmentLoader.abort();\n    this.keyLoader.abort(this.playlistType);\n    const frag = this.fragCurrent;\n    if (frag?.loader) {\n      frag.abortRequests();\n      this.fragmentTracker.removeFragment(frag);\n    }\n    this.resetTransmuxer();\n    this.fragCurrent = null;\n    this.fragPrevious = null;\n    this.clearInterval();\n    this.clearNextTick();\n    this.state = State.STOPPED;\n  }\n\n  protected _streamEnded(\n    bufferInfo: BufferInfo,\n    levelDetails: LevelDetails,\n  ): boolean {\n    // If playlist is live, there is another buffered range after the current range, nothing buffered, media is detached,\n    // of nothing loading/loaded return false\n    if (\n      levelDetails.live ||\n      bufferInfo.nextStart ||\n      !bufferInfo.end ||\n      !this.media\n    ) {\n      return false;\n    }\n    const partList = levelDetails.partList;\n    // Since the last part isn't guaranteed to correspond to the last playlist segment for Low-Latency HLS,\n    // check instead if the last part is buffered.\n    if (partList?.length) {\n      const lastPart = partList[partList.length - 1];\n\n      // Checking the midpoint of the part for potential margin of error and related issues.\n      // NOTE: Technically I believe parts could yield content that is < the computed duration (including potential a duration of 0)\n      // and still be spec-compliant, so there may still be edge cases here. Likewise, there could be issues in end of stream\n      // part mismatches for independent audio and video playlists/segments.\n      const lastPartBuffered = BufferHelper.isBuffered(\n        this.media,\n        lastPart.start + lastPart.duration / 2,\n      );\n      return lastPartBuffered;\n    }\n\n    const playlistType =\n      levelDetails.fragments[levelDetails.fragments.length - 1].type;\n    return this.fragmentTracker.isEndListAppended(playlistType);\n  }\n\n  protected getLevelDetails(): LevelDetails | undefined {\n    if (this.levels && this.levelLastLoaded !== null) {\n      return this.levelLastLoaded?.details;\n    }\n  }\n\n  protected onMediaAttached(\n    event: Events.MEDIA_ATTACHED,\n    data: MediaAttachedData,\n  ) {\n    const media = (this.media = this.mediaBuffer = data.media);\n    this.onvseeking = this.onMediaSeeking.bind(this) as EventListener;\n    this.onvended = this.onMediaEnded.bind(this) as EventListener;\n    media.addEventListener('seeking', this.onvseeking);\n    media.addEventListener('ended', this.onvended);\n    const config = this.config;\n    if (this.levels && config.autoStartLoad && this.state === State.STOPPED) {\n      this.startLoad(config.startPosition);\n    }\n  }\n\n  protected onMediaDetaching() {\n    const media = this.media;\n    if (media?.ended) {\n      this.log('MSE detaching and video ended, reset startPosition');\n      this.startPosition = this.lastCurrentTime = 0;\n    }\n\n    // remove video listeners\n    if (media && this.onvseeking && this.onvended) {\n      media.removeEventListener('seeking', this.onvseeking);\n      media.removeEventListener('ended', this.onvended);\n      this.onvseeking = this.onvended = null;\n    }\n    if (this.keyLoader) {\n      this.keyLoader.detach();\n    }\n    this.media = this.mediaBuffer = null;\n    this.loadedmetadata = false;\n    this.fragmentTracker.removeAllFragments();\n    this.stopLoad();\n  }\n\n  protected onMediaSeeking() {\n    const { config, fragCurrent, media, mediaBuffer, state } = this;\n    const currentTime: number = media ? media.currentTime : 0;\n    const bufferInfo = BufferHelper.bufferInfo(\n      mediaBuffer ? mediaBuffer : media,\n      currentTime,\n      config.maxBufferHole,\n    );\n\n    this.log(\n      `media seeking to ${\n        Number.isFinite(currentTime) ? currentTime.toFixed(3) : currentTime\n      }, state: ${state}`,\n    );\n\n    if (this.state === State.ENDED) {\n      this.resetLoadingState();\n    } else if (fragCurrent) {\n      // Seeking while frag load is in progress\n      const tolerance = config.maxFragLookUpTolerance;\n      const fragStartOffset = fragCurrent.start - tolerance;\n      const fragEndOffset =\n        fragCurrent.start + fragCurrent.duration + tolerance;\n      // if seeking out of buffered range or into new one\n      if (\n        !bufferInfo.len ||\n        fragEndOffset < bufferInfo.start ||\n        fragStartOffset > bufferInfo.end\n      ) {\n        const pastFragment = currentTime > fragEndOffset;\n        // if the seek position is outside the current fragment range\n        if (currentTime < fragStartOffset || pastFragment) {\n          if (pastFragment && fragCurrent.loader) {\n            this.log(\n              'seeking outside of buffer while fragment load in progress, cancel fragment load',\n            );\n            fragCurrent.abortRequests();\n            this.resetLoadingState();\n          }\n          this.fragPrevious = null;\n        }\n      }\n    }\n\n    if (media) {\n      // Remove gap fragments\n      this.fragmentTracker.removeFragmentsInRange(\n        currentTime,\n        Infinity,\n        this.playlistType,\n        true,\n      );\n\n      this.lastCurrentTime = currentTime;\n    }\n\n    // in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target\n    if (!this.loadedmetadata && !bufferInfo.len) {\n      this.nextLoadPosition = this.startPosition = currentTime;\n    }\n\n    // Async tick to speed up processing\n    this.tickImmediate();\n  }\n\n  protected onMediaEnded() {\n    // reset startPosition and lastCurrentTime to restart playback @ stream beginning\n    this.startPosition = this.lastCurrentTime = 0;\n  }\n\n  protected onManifestLoaded(\n    event: Events.MANIFEST_LOADED,\n    data: ManifestLoadedData,\n  ): void {\n    this.startTimeOffset = data.startTimeOffset;\n    this.initPTS = [];\n  }\n\n  protected onHandlerDestroying() {\n    this.hls.off(Events.MANIFEST_LOADED, this.onManifestLoaded, this);\n    this.stopLoad();\n    super.onHandlerDestroying();\n    // @ts-ignore\n    this.hls = null;\n  }\n\n  protected onHandlerDestroyed() {\n    this.state = State.STOPPED;\n    if (this.fragmentLoader) {\n      this.fragmentLoader.destroy();\n    }\n    if (this.keyLoader) {\n      this.keyLoader.destroy();\n    }\n    if (this.decrypter) {\n      this.decrypter.destroy();\n    }\n\n    this.hls =\n      this.log =\n      this.warn =\n      this.decrypter =\n      this.keyLoader =\n      this.fragmentLoader =\n      this.fragmentTracker =\n        null as any;\n    super.onHandlerDestroyed();\n  }\n\n  protected loadFragment(\n    frag: Fragment,\n    level: Level,\n    targetBufferTime: number,\n  ) {\n    this._loadFragForPlayback(frag, level, targetBufferTime);\n  }\n\n  private _loadFragForPlayback(\n    frag: Fragment,\n    level: Level,\n    targetBufferTime: number,\n  ) {\n    const progressCallback: FragmentLoadProgressCallback = (\n      data: FragLoadedData,\n    ) => {\n      if (this.fragContextChanged(frag)) {\n        this.warn(\n          `Fragment ${frag.sn}${\n            data.part ? ' p: ' + data.part.index : ''\n          } of level ${frag.level} was dropped during download.`,\n        );\n        this.fragmentTracker.removeFragment(frag);\n        return;\n      }\n      frag.stats.chunkCount++;\n      this._handleFragmentLoadProgress(data);\n    };\n\n    this._doFragLoad(frag, level, targetBufferTime, progressCallback)\n      .then((data) => {\n        if (!data) {\n          // if we're here we probably needed to backtrack or are waiting for more parts\n          return;\n        }\n        const state = this.state;\n        if (this.fragContextChanged(frag)) {\n          if (\n            state === State.FRAG_LOADING ||\n            (!this.fragCurrent && state === State.PARSING)\n          ) {\n            this.fragmentTracker.removeFragment(frag);\n            this.state = State.IDLE;\n          }\n          return;\n        }\n\n        if ('payload' in data) {\n          this.log(`Loaded fragment ${frag.sn} of level ${frag.level}`);\n          this.hls.trigger(Events.FRAG_LOADED, data);\n        }\n\n        // Pass through the whole payload; controllers not implementing progressive loading receive data from this callback\n        this._handleFragmentLoadComplete(data);\n      })\n      .catch((reason) => {\n        if (this.state === State.STOPPED || this.state === State.ERROR) {\n          return;\n        }\n        this.warn(`Frag error: ${reason?.message || reason}`);\n        this.resetFragmentLoading(frag);\n      });\n  }\n\n  protected clearTrackerIfNeeded(frag: Fragment) {\n    const { fragmentTracker } = this;\n    const fragState = fragmentTracker.getState(frag);\n    if (fragState === FragmentState.APPENDING) {\n      // Lower the max buffer length and try again\n      const playlistType = frag.type as PlaylistLevelType;\n      const bufferedInfo = this.getFwdBufferInfo(\n        this.mediaBuffer,\n        playlistType,\n      );\n      const minForwardBufferLength = Math.max(\n        frag.duration,\n        bufferedInfo ? bufferedInfo.len : this.config.maxBufferLength,\n      );\n      // If backtracking, always remove from the tracker without reducing max buffer length\n      const backtrackFragment = (this as any).backtrackFragment as\n        | Fragment\n        | undefined;\n      const backtracked = backtrackFragment\n        ? (frag.sn as number) - (backtrackFragment.sn as number)\n        : 0;\n      if (\n        backtracked === 1 ||\n        this.reduceMaxBufferLength(minForwardBufferLength, frag.duration)\n      ) {\n        fragmentTracker.removeFragment(frag);\n      }\n    } else if (this.mediaBuffer?.buffered.length === 0) {\n      // Stop gap for bad tracker / buffer flush behavior\n      fragmentTracker.removeAllFragments();\n    } else if (fragmentTracker.hasParts(frag.type)) {\n      // In low latency mode, remove fragments for which only some parts were buffered\n      fragmentTracker.detectPartialFragments({\n        frag,\n        part: null,\n        stats: frag.stats,\n        id: frag.type,\n      });\n      if (fragmentTracker.getState(frag) === FragmentState.PARTIAL) {\n        fragmentTracker.removeFragment(frag);\n      }\n    }\n  }\n\n  protected checkLiveUpdate(details: LevelDetails) {\n    if (details.updated && !details.live) {\n      // Live stream ended, update fragment tracker\n      const lastFragment = details.fragments[details.fragments.length - 1];\n      this.fragmentTracker.detectPartialFragments({\n        frag: lastFragment,\n        part: null,\n        stats: lastFragment.stats,\n        id: lastFragment.type,\n      });\n    }\n    if (!details.fragments[0]) {\n      details.deltaUpdateFailed = true;\n    }\n  }\n\n  protected flushMainBuffer(\n    startOffset: number,\n    endOffset: number,\n    type: SourceBufferName | null = null,\n  ) {\n    if (!(startOffset - endOffset)) {\n      return;\n    }\n    // When alternate audio is playing, the audio-stream-controller is responsible for the audio buffer. Otherwise,\n    // passing a null type flushes both buffers\n    const flushScope: BufferFlushingData = { startOffset, endOffset, type };\n    this.hls.trigger(Events.BUFFER_FLUSHING, flushScope);\n  }\n\n  protected _loadInitSegment(frag: Fragment, level: Level) {\n    this._doFragLoad(frag, level)\n      .then((data) => {\n        if (!data || this.fragContextChanged(frag) || !this.levels) {\n          throw new Error('init load aborted');\n        }\n\n        return data;\n      })\n      .then((data: FragLoadedData) => {\n        const { hls } = this;\n        const { payload } = data;\n        const decryptData = frag.decryptdata;\n\n        // check to see if the payload needs to be decrypted\n        if (\n          payload &&\n          payload.byteLength > 0 &&\n          decryptData?.key &&\n          decryptData.iv &&\n          decryptData.method === 'AES-128'\n        ) {\n          const startTime = self.performance.now();\n          // decrypt init segment data\n          return this.decrypter\n            .decrypt(\n              new Uint8Array(payload),\n              decryptData.key.buffer,\n              decryptData.iv.buffer,\n            )\n            .catch((err) => {\n              hls.trigger(Events.ERROR, {\n                type: ErrorTypes.MEDIA_ERROR,\n                details: ErrorDetails.FRAG_DECRYPT_ERROR,\n                fatal: false,\n                error: err,\n                reason: err.message,\n                frag,\n              });\n              throw err;\n            })\n            .then((decryptedData) => {\n              const endTime = self.performance.now();\n              hls.trigger(Events.FRAG_DECRYPTED, {\n                frag,\n                payload: decryptedData,\n                stats: {\n                  tstart: startTime,\n                  tdecrypt: endTime,\n                },\n              });\n              data.payload = decryptedData;\n              return this.completeInitSegmentLoad(data);\n            });\n        }\n        return this.completeInitSegmentLoad(data);\n      })\n      .catch((reason) => {\n        if (this.state === State.STOPPED || this.state === State.ERROR) {\n          return;\n        }\n        this.warn(reason);\n        this.resetFragmentLoading(frag);\n      });\n  }\n\n  private completeInitSegmentLoad(data: FragLoadedData) {\n    const { levels } = this;\n    if (!levels) {\n      throw new Error('init load aborted, missing levels');\n    }\n    const stats = data.frag.stats;\n    this.state = State.IDLE;\n    data.frag.data = new Uint8Array(data.payload);\n    stats.parsing.start = stats.buffering.start = self.performance.now();\n    stats.parsing.end = stats.buffering.end = self.performance.now();\n    this.tick();\n  }\n\n  protected fragContextChanged(frag: Fragment | null) {\n    const { fragCurrent } = this;\n    return (\n      !frag ||\n      !fragCurrent ||\n      frag.sn !== fragCurrent.sn ||\n      frag.level !== fragCurrent.level\n    );\n  }\n\n  protected fragBufferedComplete(frag: Fragment, part: Part | null) {\n    const media = this.mediaBuffer ? this.mediaBuffer : this.media;\n    this.log(\n      `Buffered ${frag.type} sn: ${frag.sn}${\n        part ? ' part: ' + part.index : ''\n      } of ${\n        this.playlistType === PlaylistLevelType.MAIN ? 'level' : 'track'\n      } ${frag.level} (frag:[${(frag.startPTS ?? NaN).toFixed(3)}-${(\n        frag.endPTS ?? NaN\n      ).toFixed(3)}] > buffer:${\n        media\n          ? TimeRanges.toString(BufferHelper.getBuffered(media))\n          : '(detached)'\n      })`,\n    );\n    if (frag.sn !== 'initSegment') {\n      if (frag.type !== PlaylistLevelType.SUBTITLE) {\n        const el = frag.elementaryStreams;\n        if (!Object.keys(el).some((type) => !!el[type])) {\n          // empty segment\n          this.state = State.IDLE;\n          return;\n        }\n      }\n      const level = this.levels?.[frag.level];\n      if (level?.fragmentError) {\n        this.log(\n          `Resetting level fragment error count of ${level.fragmentError} on frag buffered`,\n        );\n        level.fragmentError = 0;\n      }\n    }\n    this.state = State.IDLE;\n    if (!media) {\n      return;\n    }\n    if (\n      !this.loadedmetadata &&\n      frag.type == PlaylistLevelType.MAIN &&\n      media.buffered.length &&\n      this.fragCurrent?.sn === this.fragPrevious?.sn\n    ) {\n      this.loadedmetadata = true;\n      this.seekToStartPos();\n    }\n    this.tick();\n  }\n\n  protected seekToStartPos() {}\n\n  protected _handleFragmentLoadComplete(fragLoadedEndData: PartsLoadedData) {\n    const { transmuxer } = this;\n    if (!transmuxer) {\n      return;\n    }\n    const { frag, part, partsLoaded } = fragLoadedEndData;\n    // If we did not load parts, or loaded all parts, we have complete (not partial) fragment data\n    const complete =\n      !partsLoaded ||\n      partsLoaded.length === 0 ||\n      partsLoaded.some((fragLoaded) => !fragLoaded);\n    const chunkMeta = new ChunkMetadata(\n      frag.level,\n      frag.sn as number,\n      frag.stats.chunkCount + 1,\n      0,\n      part ? part.index : -1,\n      !complete,\n    );\n    transmuxer.flush(chunkMeta);\n  }\n\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  protected _handleFragmentLoadProgress(\n    frag: PartsLoadedData | FragLoadedData,\n  ) {}\n\n  protected _doFragLoad(\n    frag: Fragment,\n    level: Level,\n    targetBufferTime: number | null = null,\n    progressCallback?: FragmentLoadProgressCallback,\n  ): Promise<PartsLoadedData | FragLoadedData | null> {\n    const details = level?.details;\n    if (!this.levels || !details) {\n      throw new Error(\n        `frag load aborted, missing level${details ? '' : ' detail'}s`,\n      );\n    }\n\n    let keyLoadingPromise: Promise<KeyLoadedData | void> | null = null;\n    if (frag.encrypted && !frag.decryptdata?.key) {\n      this.log(\n        `Loading key for ${frag.sn} of [${details.startSN}-${details.endSN}], ${\n          this.logPrefix === '[stream-controller]' ? 'level' : 'track'\n        } ${frag.level}`,\n      );\n      this.state = State.KEY_LOADING;\n      this.fragCurrent = frag;\n      keyLoadingPromise = this.keyLoader.load(frag).then((keyLoadedData) => {\n        if (!this.fragContextChanged(keyLoadedData.frag)) {\n          this.hls.trigger(Events.KEY_LOADED, keyLoadedData);\n          if (this.state === State.KEY_LOADING) {\n            this.state = State.IDLE;\n          }\n          return keyLoadedData;\n        }\n      });\n      this.hls.trigger(Events.KEY_LOADING, { frag });\n      if (this.fragCurrent === null) {\n        keyLoadingPromise = Promise.reject(\n          new Error(`frag load aborted, context changed in KEY_LOADING`),\n        );\n      }\n    } else if (!frag.encrypted && details.encryptedFragments.length) {\n      this.keyLoader.loadClear(frag, details.encryptedFragments);\n    }\n\n    targetBufferTime = Math.max(frag.start, targetBufferTime || 0);\n    if (this.config.lowLatencyMode && frag.sn !== 'initSegment') {\n      const partList = details.partList;\n      if (partList && progressCallback) {\n        if (targetBufferTime > frag.end && details.fragmentHint) {\n          frag = details.fragmentHint;\n        }\n        const partIndex = this.getNextPart(partList, frag, targetBufferTime);\n        if (partIndex > -1) {\n          const part = partList[partIndex];\n          this.log(\n            `Loading part sn: ${frag.sn} p: ${part.index} cc: ${\n              frag.cc\n            } of playlist [${details.startSN}-${\n              details.endSN\n            }] parts [0-${partIndex}-${partList.length - 1}] ${\n              this.logPrefix === '[stream-controller]' ? 'level' : 'track'\n            }: ${frag.level}, target: ${parseFloat(\n              targetBufferTime.toFixed(3),\n            )}`,\n          );\n          this.nextLoadPosition = part.start + part.duration;\n          this.state = State.FRAG_LOADING;\n          let result: Promise<PartsLoadedData | FragLoadedData | null>;\n          if (keyLoadingPromise) {\n            result = keyLoadingPromise\n              .then((keyLoadedData) => {\n                if (\n                  !keyLoadedData ||\n                  this.fragContextChanged(keyLoadedData.frag)\n                ) {\n                  return null;\n                }\n                return this.doFragPartsLoad(\n                  frag,\n                  part,\n                  level,\n                  progressCallback,\n                );\n              })\n              .catch((error) => this.handleFragLoadError(error));\n          } else {\n            result = this.doFragPartsLoad(\n              frag,\n              part,\n              level,\n              progressCallback,\n            ).catch((error: LoadError) => this.handleFragLoadError(error));\n          }\n          this.hls.trigger(Events.FRAG_LOADING, {\n            frag,\n            part,\n            targetBufferTime,\n          });\n          if (this.fragCurrent === null) {\n            return Promise.reject(\n              new Error(\n                `frag load aborted, context changed in FRAG_LOADING parts`,\n              ),\n            );\n          }\n          return result;\n        } else if (\n          !frag.url ||\n          this.loadedEndOfParts(partList, targetBufferTime)\n        ) {\n          // Fragment hint has no parts\n          return Promise.resolve(null);\n        }\n      }\n    }\n\n    this.log(\n      `Loading fragment ${frag.sn} cc: ${frag.cc} ${\n        details ? 'of [' + details.startSN + '-' + details.endSN + '] ' : ''\n      }${this.logPrefix === '[stream-controller]' ? 'level' : 'track'}: ${\n        frag.level\n      }, target: ${parseFloat(targetBufferTime.toFixed(3))}`,\n    );\n    // Don't update nextLoadPosition for fragments which are not buffered\n    if (Number.isFinite(frag.sn as number) && !this.bitrateTest) {\n      this.nextLoadPosition = frag.start + frag.duration;\n    }\n    this.state = State.FRAG_LOADING;\n\n    // Load key before streaming fragment data\n    const dataOnProgress = this.config.progressive;\n    let result: Promise<PartsLoadedData | FragLoadedData | null>;\n    if (dataOnProgress && keyLoadingPromise) {\n      result = keyLoadingPromise\n        .then((keyLoadedData) => {\n          if (!keyLoadedData || this.fragContextChanged(keyLoadedData?.frag)) {\n            return null;\n          }\n          return this.fragmentLoader.load(frag, progressCallback);\n        })\n        .catch((error) => this.handleFragLoadError(error));\n    } else {\n      // load unencrypted fragment data with progress event,\n      // or handle fragment result after key and fragment are finished loading\n      result = Promise.all([\n        this.fragmentLoader.load(\n          frag,\n          dataOnProgress ? progressCallback : undefined,\n        ),\n        keyLoadingPromise,\n      ])\n        .then(([fragLoadedData]) => {\n          if (!dataOnProgress && fragLoadedData && progressCallback) {\n            progressCallback(fragLoadedData);\n          }\n          return fragLoadedData;\n        })\n        .catch((error) => this.handleFragLoadError(error));\n    }\n    this.hls.trigger(Events.FRAG_LOADING, { frag, targetBufferTime });\n    if (this.fragCurrent === null) {\n      return Promise.reject(\n        new Error(`frag load aborted, context changed in FRAG_LOADING`),\n      );\n    }\n    return result;\n  }\n\n  private doFragPartsLoad(\n    frag: Fragment,\n    fromPart: Part,\n    level: Level,\n    progressCallback: FragmentLoadProgressCallback,\n  ): Promise<PartsLoadedData | null> {\n    return new Promise(\n      (resolve: ResolveFragLoaded, reject: RejectFragLoaded) => {\n        const partsLoaded: FragLoadedData[] = [];\n        const initialPartList = level.details?.partList;\n        const loadPart = (part: Part) => {\n          this.fragmentLoader\n            .loadPart(frag, part, progressCallback)\n            .then((partLoadedData: FragLoadedData) => {\n              partsLoaded[part.index] = partLoadedData;\n              const loadedPart = partLoadedData.part as Part;\n              this.hls.trigger(Events.FRAG_LOADED, partLoadedData);\n              const nextPart =\n                getPartWith(level, frag.sn as number, part.index + 1) ||\n                findPart(initialPartList, frag.sn as number, part.index + 1);\n              if (nextPart) {\n                loadPart(nextPart);\n              } else {\n                return resolve({\n                  frag,\n                  part: loadedPart,\n                  partsLoaded,\n                });\n              }\n            })\n            .catch(reject);\n        };\n        loadPart(fromPart);\n      },\n    );\n  }\n\n  private handleFragLoadError(error: LoadError | Error) {\n    if ('data' in error) {\n      const data = error.data;\n      if (error.data && data.details === ErrorDetails.INTERNAL_ABORTED) {\n        this.handleFragLoadAborted(data.frag, data.part);\n      } else {\n        this.hls.trigger(Events.ERROR, data as ErrorData);\n      }\n    } else {\n      this.hls.trigger(Events.ERROR, {\n        type: ErrorTypes.OTHER_ERROR,\n        details: ErrorDetails.INTERNAL_EXCEPTION,\n        err: error,\n        error,\n        fatal: true,\n      });\n    }\n    return null;\n  }\n\n  protected _handleTransmuxerFlush(chunkMeta: ChunkMetadata) {\n    const context = this.getCurrentContext(chunkMeta);\n    if (!context || this.state !== State.PARSING) {\n      if (\n        !this.fragCurrent &&\n        this.state !== State.STOPPED &&\n        this.state !== State.ERROR\n      ) {\n        this.state = State.IDLE;\n      }\n      return;\n    }\n    const { frag, part, level } = context;\n    const now = self.performance.now();\n    frag.stats.parsing.end = now;\n    if (part) {\n      part.stats.parsing.end = now;\n    }\n    this.updateLevelTiming(frag, part, level, chunkMeta.partial);\n  }\n\n  protected getCurrentContext(\n    chunkMeta: ChunkMetadata,\n  ): { frag: Fragment; part: Part | null; level: Level } | null {\n    const { levels, fragCurrent } = this;\n    const { level: levelIndex, sn, part: partIndex } = chunkMeta;\n    if (!levels?.[levelIndex]) {\n      this.warn(\n        `Levels object was unset while buffering fragment ${sn} of level ${levelIndex}. The current chunk will not be buffered.`,\n      );\n      return null;\n    }\n    const level = levels[levelIndex];\n    const part = partIndex > -1 ? getPartWith(level, sn, partIndex) : null;\n    const frag = part\n      ? part.fragment\n      : getFragmentWithSN(level, sn, fragCurrent);\n    if (!frag) {\n      return null;\n    }\n    if (fragCurrent && fragCurrent !== frag) {\n      frag.stats = fragCurrent.stats;\n    }\n    return { frag, part, level };\n  }\n\n  protected bufferFragmentData(\n    data: RemuxedTrack,\n    frag: Fragment,\n    part: Part | null,\n    chunkMeta: ChunkMetadata,\n    noBacktracking?: boolean,\n  ) {\n    if (!data || this.state !== State.PARSING) {\n      return;\n    }\n\n    const { data1, data2 } = data;\n    let buffer = data1;\n    if (data1 && data2) {\n      // Combine the moof + mdat so that we buffer with a single append\n      buffer = appendUint8Array(data1, data2);\n    }\n\n    if (!buffer?.length) {\n      return;\n    }\n\n    const segment: BufferAppendingData = {\n      type: data.type,\n      frag,\n      part,\n      chunkMeta,\n      parent: frag.type,\n      data: buffer,\n    };\n    this.hls.trigger(Events.BUFFER_APPENDING, segment);\n\n    if (data.dropped && data.independent && !part) {\n      if (noBacktracking) {\n        return;\n      }\n      // Clear buffer so that we reload previous segments sequentially if required\n      this.flushBufferGap(frag);\n    }\n  }\n\n  protected flushBufferGap(frag: Fragment) {\n    const media = this.media;\n    if (!media) {\n      return;\n    }\n    // If currentTime is not buffered, clear the back buffer so that we can backtrack as much as needed\n    if (!BufferHelper.isBuffered(media, media.currentTime)) {\n      this.flushMainBuffer(0, frag.start);\n      return;\n    }\n    // Remove back-buffer without interrupting playback to allow back tracking\n    const currentTime = media.currentTime;\n    const bufferInfo = BufferHelper.bufferInfo(media, currentTime, 0);\n    const fragDuration = frag.duration;\n    const segmentFraction = Math.min(\n      this.config.maxFragLookUpTolerance * 2,\n      fragDuration * 0.25,\n    );\n    const start = Math.max(\n      Math.min(frag.start - segmentFraction, bufferInfo.end - segmentFraction),\n      currentTime + segmentFraction,\n    );\n    if (frag.start - start > segmentFraction) {\n      this.flushMainBuffer(start, frag.start);\n    }\n  }\n\n  protected getFwdBufferInfo(\n    bufferable: Bufferable | null,\n    type: PlaylistLevelType,\n  ): BufferInfo | null {\n    const pos = this.getLoadPosition();\n    if (!Number.isFinite(pos)) {\n      return null;\n    }\n    return this.getFwdBufferInfoAtPos(bufferable, pos, type);\n  }\n\n  protected getFwdBufferInfoAtPos(\n    bufferable: Bufferable | null,\n    pos: number,\n    type: PlaylistLevelType,\n  ): BufferInfo | null {\n    const {\n      config: { maxBufferHole },\n    } = this;\n    const bufferInfo = BufferHelper.bufferInfo(bufferable, pos, maxBufferHole);\n    // Workaround flaw in getting forward buffer when maxBufferHole is smaller than gap at current pos\n    if (bufferInfo.len === 0 && bufferInfo.nextStart !== undefined) {\n      const bufferedFragAtPos = this.fragmentTracker.getBufferedFrag(pos, type);\n      if (bufferedFragAtPos && bufferInfo.nextStart < bufferedFragAtPos.end) {\n        return BufferHelper.bufferInfo(\n          bufferable,\n          pos,\n          Math.max(bufferInfo.nextStart, maxBufferHole),\n        );\n      }\n    }\n    return bufferInfo;\n  }\n\n  protected getMaxBufferLength(levelBitrate?: number): number {\n    const { config } = this;\n    let maxBufLen;\n    if (levelBitrate) {\n      maxBufLen = Math.max(\n        (8 * config.maxBufferSize) / levelBitrate,\n        config.maxBufferLength,\n      );\n    } else {\n      maxBufLen = config.maxBufferLength;\n    }\n    return Math.min(maxBufLen, config.maxMaxBufferLength);\n  }\n\n  protected reduceMaxBufferLength(threshold: number, fragDuration: number) {\n    const config = this.config;\n    const minLength = Math.max(\n      Math.min(threshold - fragDuration, config.maxBufferLength),\n      fragDuration,\n    );\n    const reducedLength = Math.max(\n      threshold - fragDuration * 3,\n      config.maxMaxBufferLength / 2,\n      minLength,\n    );\n    if (reducedLength >= minLength) {\n      // reduce max buffer length as it might be too high. we do this to avoid loop flushing ...\n      config.maxMaxBufferLength = reducedLength;\n      this.warn(`Reduce max buffer length to ${reducedLength}s`);\n      return true;\n    }\n    return false;\n  }\n\n  protected getAppendedFrag(\n    position: number,\n    playlistType: PlaylistLevelType = PlaylistLevelType.MAIN,\n  ): Fragment | null {\n    const fragOrPart = this.fragmentTracker.getAppendedFrag(\n      position,\n      PlaylistLevelType.MAIN,\n    );\n    if (fragOrPart && 'fragment' in fragOrPart) {\n      return fragOrPart.fragment;\n    }\n    return fragOrPart;\n  }\n\n  protected getNextFragment(\n    pos: number,\n    levelDetails: LevelDetails,\n  ): Fragment | null {\n    const fragments = levelDetails.fragments;\n    const fragLen = fragments.length;\n\n    if (!fragLen) {\n      return null;\n    }\n\n    // find fragment index, contiguous with end of buffer position\n    const { config } = this;\n    const start = fragments[0].start;\n    let frag;\n\n    if (levelDetails.live) {\n      const initialLiveManifestSize = config.initialLiveManifestSize;\n      if (fragLen < initialLiveManifestSize) {\n        this.warn(\n          `Not enough fragments to start playback (have: ${fragLen}, need: ${initialLiveManifestSize})`,\n        );\n        return null;\n      }\n      // The real fragment start times for a live stream are only known after the PTS range for that level is known.\n      // In order to discover the range, we load the best matching fragment for that level and demux it.\n      // Do not load using live logic if the starting frag is requested - we want to use getFragmentAtPosition() so that\n      // we get the fragment matching that start time\n      if (\n        (!levelDetails.PTSKnown &&\n          !this.startFragRequested &&\n          this.startPosition === -1) ||\n        pos < start\n      ) {\n        frag = this.getInitialLiveFragment(levelDetails, fragments);\n        this.startPosition = this.nextLoadPosition = frag\n          ? this.hls.liveSyncPosition || frag.start\n          : pos;\n      }\n    } else if (pos <= start) {\n      // VoD playlist: if loadPosition before start of playlist, load first fragment\n      frag = fragments[0];\n    }\n\n    // If we haven't run into any special cases already, just load the fragment most closely matching the requested position\n    if (!frag) {\n      const end = config.lowLatencyMode\n        ? levelDetails.partEnd\n        : levelDetails.fragmentEnd;\n      frag = this.getFragmentAtPosition(pos, end, levelDetails);\n    }\n\n    return this.mapToInitFragWhenRequired(frag);\n  }\n\n  protected isLoopLoading(frag: Fragment, targetBufferTime: number): boolean {\n    const trackerState = this.fragmentTracker.getState(frag);\n    return (\n      (trackerState === FragmentState.OK ||\n        (trackerState === FragmentState.PARTIAL && !!frag.gap)) &&\n      this.nextLoadPosition > targetBufferTime\n    );\n  }\n\n  protected getNextFragmentLoopLoading(\n    frag: Fragment,\n    levelDetails: LevelDetails,\n    bufferInfo: BufferInfo,\n    playlistType: PlaylistLevelType,\n    maxBufLen: number,\n  ): Fragment | null {\n    const gapStart = frag.gap;\n    const nextFragment = this.getNextFragment(\n      this.nextLoadPosition,\n      levelDetails,\n    );\n    if (nextFragment === null) {\n      return nextFragment;\n    }\n    frag = nextFragment;\n    if (gapStart && frag && !frag.gap && bufferInfo.nextStart) {\n      // Media buffered after GAP tags should not make the next buffer timerange exceed forward buffer length\n      const nextbufferInfo = this.getFwdBufferInfoAtPos(\n        this.mediaBuffer ? this.mediaBuffer : this.media,\n        bufferInfo.nextStart,\n        playlistType,\n      );\n      if (\n        nextbufferInfo !== null &&\n        bufferInfo.len + nextbufferInfo.len >= maxBufLen\n      ) {\n        // Returning here might result in not finding an audio and video candiate to skip to\n        this.log(\n          `buffer full after gaps in \"${playlistType}\" playlist starting at sn: ${frag.sn}`,\n        );\n        return null;\n      }\n    }\n    return frag;\n  }\n\n  mapToInitFragWhenRequired(frag: Fragment | null): typeof frag {\n    // If an initSegment is present, it must be buffered first\n    if (frag?.initSegment && !frag?.initSegment.data && !this.bitrateTest) {\n      return frag.initSegment;\n    }\n\n    return frag;\n  }\n\n  getNextPart(\n    partList: Part[],\n    frag: Fragment,\n    targetBufferTime: number,\n  ): number {\n    let nextPart = -1;\n    let contiguous = false;\n    let independentAttrOmitted = true;\n    for (let i = 0, len = partList.length; i < len; i++) {\n      const part = partList[i];\n      independentAttrOmitted = independentAttrOmitted && !part.independent;\n      if (nextPart > -1 && targetBufferTime < part.start) {\n        break;\n      }\n      const loaded = part.loaded;\n      if (loaded) {\n        nextPart = -1;\n      } else if (\n        (contiguous || part.independent || independentAttrOmitted) &&\n        part.fragment === frag\n      ) {\n        nextPart = i;\n      }\n      contiguous = loaded;\n    }\n    return nextPart;\n  }\n\n  private loadedEndOfParts(\n    partList: Part[],\n    targetBufferTime: number,\n  ): boolean {\n    const lastPart = partList[partList.length - 1];\n    return lastPart && targetBufferTime > lastPart.start && lastPart.loaded;\n  }\n\n  /*\n   This method is used find the best matching first fragment for a live playlist. This fragment is used to calculate the\n   \"sliding\" of the playlist, which is its offset from the start of playback. After sliding we can compute the real\n   start and end times for each fragment in the playlist (after which this method will not need to be called).\n  */\n  protected getInitialLiveFragment(\n    levelDetails: LevelDetails,\n    fragments: Array<Fragment>,\n  ): Fragment | null {\n    const fragPrevious = this.fragPrevious;\n    let frag: Fragment | null = null;\n    if (fragPrevious) {\n      if (levelDetails.hasProgramDateTime) {\n        // Prefer using PDT, because it can be accurate enough to choose the correct fragment without knowing the level sliding\n        this.log(\n          `Live playlist, switching playlist, load frag with same PDT: ${fragPrevious.programDateTime}`,\n        );\n        frag = findFragmentByPDT(\n          fragments,\n          fragPrevious.endProgramDateTime,\n          this.config.maxFragLookUpTolerance,\n        );\n      }\n      if (!frag) {\n        // SN does not need to be accurate between renditions, but depending on the packaging it may be so.\n        const targetSN = (fragPrevious.sn as number) + 1;\n        if (\n          targetSN >= levelDetails.startSN &&\n          targetSN <= levelDetails.endSN\n        ) {\n          const fragNext = fragments[targetSN - levelDetails.startSN];\n          // Ensure that we're staying within the continuity range, since PTS resets upon a new range\n          if (fragPrevious.cc === fragNext.cc) {\n            frag = fragNext;\n            this.log(\n              `Live playlist, switching playlist, load frag with next SN: ${\n                frag!.sn\n              }`,\n            );\n          }\n        }\n        // It's important to stay within the continuity range if available; otherwise the fragments in the playlist\n        // will have the wrong start times\n        if (!frag) {\n          frag = findFragWithCC(fragments, fragPrevious.cc);\n          if (frag) {\n            this.log(\n              `Live playlist, switching playlist, load frag with same CC: ${frag.sn}`,\n            );\n          }\n        }\n      }\n    } else {\n      // Find a new start fragment when fragPrevious is null\n      const liveStart = this.hls.liveSyncPosition;\n      if (liveStart !== null) {\n        frag = this.getFragmentAtPosition(\n          liveStart,\n          this.bitrateTest ? levelDetails.fragmentEnd : levelDetails.edge,\n          levelDetails,\n        );\n      }\n    }\n\n    return frag;\n  }\n\n  /*\n  This method finds the best matching fragment given the provided position.\n   */\n  protected getFragmentAtPosition(\n    bufferEnd: number,\n    end: number,\n    levelDetails: LevelDetails,\n  ): Fragment | null {\n    const { config } = this;\n    let { fragPrevious } = this;\n    let { fragments, endSN } = levelDetails;\n    const { fragmentHint } = levelDetails;\n    const { maxFragLookUpTolerance } = config;\n    const partList = levelDetails.partList;\n\n    const loadingParts = !!(\n      config.lowLatencyMode &&\n      partList?.length &&\n      fragmentHint\n    );\n    if (loadingParts && fragmentHint && !this.bitrateTest) {\n      // Include incomplete fragment with parts at end\n      fragments = fragments.concat(fragmentHint);\n      endSN = fragmentHint.sn as number;\n    }\n\n    let frag;\n    if (bufferEnd < end) {\n      const lookupTolerance =\n        bufferEnd > end - maxFragLookUpTolerance ? 0 : maxFragLookUpTolerance;\n      // Remove the tolerance if it would put the bufferEnd past the actual end of stream\n      // Uses buffer and sequence number to calculate switch segment (required if using EXT-X-DISCONTINUITY-SEQUENCE)\n      frag = findFragmentByPTS(\n        fragPrevious,\n        fragments,\n        bufferEnd,\n        lookupTolerance,\n      );\n    } else {\n      // reach end of playlist\n      frag = fragments[fragments.length - 1];\n    }\n\n    if (frag) {\n      const curSNIdx = frag.sn - levelDetails.startSN;\n      // Move fragPrevious forward to support forcing the next fragment to load\n      // when the buffer catches up to a previously buffered range.\n      const fragState = this.fragmentTracker.getState(frag);\n      if (\n        fragState === FragmentState.OK ||\n        (fragState === FragmentState.PARTIAL && frag.gap)\n      ) {\n        fragPrevious = frag;\n      }\n      if (\n        fragPrevious &&\n        frag.sn === fragPrevious.sn &&\n        (!loadingParts || partList[0].fragment.sn > frag.sn)\n      ) {\n        // Force the next fragment to load if the previous one was already selected. This can occasionally happen with\n        // non-uniform fragment durations\n        const sameLevel = fragPrevious && frag.level === fragPrevious.level;\n        if (sameLevel) {\n          const nextFrag = fragments[curSNIdx + 1];\n          if (\n            frag.sn < endSN &&\n            this.fragmentTracker.getState(nextFrag) !== FragmentState.OK\n          ) {\n            frag = nextFrag;\n          } else {\n            frag = null;\n          }\n        }\n      }\n    }\n    return frag;\n  }\n\n  protected synchronizeToLiveEdge(levelDetails: LevelDetails) {\n    const { config, media } = this;\n    if (!media) {\n      return;\n    }\n    const liveSyncPosition = this.hls.liveSyncPosition;\n    const currentTime = media.currentTime;\n    const start = levelDetails.fragments[0].start;\n    const end = levelDetails.edge;\n    const withinSlidingWindow =\n      currentTime >= start - config.maxFragLookUpTolerance &&\n      currentTime <= end;\n    // Continue if we can seek forward to sync position or if current time is outside of sliding window\n    if (\n      liveSyncPosition !== null &&\n      media.duration > liveSyncPosition &&\n      (currentTime < liveSyncPosition || !withinSlidingWindow)\n    ) {\n      // Continue if buffer is starving or if current time is behind max latency\n      const maxLatency =\n        config.liveMaxLatencyDuration !== undefined\n          ? config.liveMaxLatencyDuration\n          : config.liveMaxLatencyDurationCount * levelDetails.targetduration;\n      if (\n        (!withinSlidingWindow && media.readyState < 4) ||\n        currentTime < end - maxLatency\n      ) {\n        if (!this.loadedmetadata) {\n          this.nextLoadPosition = liveSyncPosition;\n        }\n        // Only seek if ready and there is not a significant forward buffer available for playback\n        if (media.readyState) {\n          this.warn(\n            `Playback: ${currentTime.toFixed(\n              3,\n            )} is located too far from the end of live sliding playlist: ${end}, reset currentTime to : ${liveSyncPosition.toFixed(\n              3,\n            )}`,\n          );\n          media.currentTime = liveSyncPosition;\n        }\n      }\n    }\n  }\n\n  protected alignPlaylists(\n    details: LevelDetails,\n    previousDetails: LevelDetails | undefined,\n    switchDetails: LevelDetails | undefined,\n  ): number {\n    // FIXME: If not for `shouldAlignOnDiscontinuities` requiring fragPrevious.cc,\n    //  this could all go in level-helper mergeDetails()\n    const length = details.fragments.length;\n    if (!length) {\n      this.warn(`No fragments in live playlist`);\n      return 0;\n    }\n    const slidingStart = details.fragments[0].start;\n    const firstLevelLoad = !previousDetails;\n    const aligned = details.alignedSliding && Number.isFinite(slidingStart);\n    if (firstLevelLoad || (!aligned && !slidingStart)) {\n      const { fragPrevious } = this;\n      alignStream(fragPrevious, switchDetails, details);\n      const alignedSlidingStart = details.fragments[0].start;\n      this.log(\n        `Live playlist sliding: ${alignedSlidingStart.toFixed(2)} start-sn: ${\n          previousDetails ? previousDetails.startSN : 'na'\n        }->${details.startSN} prev-sn: ${\n          fragPrevious ? fragPrevious.sn : 'na'\n        } fragments: ${length}`,\n      );\n      return alignedSlidingStart;\n    }\n    return slidingStart;\n  }\n\n  protected waitForCdnTuneIn(details: LevelDetails) {\n    // Wait for Low-Latency CDN Tune-in to get an updated playlist\n    const advancePartLimit = 3;\n    return (\n      details.live &&\n      details.canBlockReload &&\n      details.partTarget &&\n      details.tuneInGoal >\n        Math.max(details.partHoldBack, details.partTarget * advancePartLimit)\n    );\n  }\n\n  protected setStartPosition(details: LevelDetails, sliding: number) {\n    // compute start position if set to -1. use it straight away if value is defined\n    let startPosition = this.startPosition;\n    if (startPosition < sliding) {\n      startPosition = -1;\n    }\n    if (startPosition === -1 || this.lastCurrentTime === -1) {\n      // Use Playlist EXT-X-START:TIME-OFFSET when set\n      // Prioritize Multivariant Playlist offset so that main, audio, and subtitle stream-controller start times match\n      const offsetInMultivariantPlaylist = this.startTimeOffset !== null;\n      const startTimeOffset = offsetInMultivariantPlaylist\n        ? this.startTimeOffset\n        : details.startTimeOffset;\n      if (startTimeOffset !== null && Number.isFinite(startTimeOffset)) {\n        startPosition = sliding + startTimeOffset;\n        if (startTimeOffset < 0) {\n          startPosition += details.totalduration;\n        }\n        startPosition = Math.min(\n          Math.max(sliding, startPosition),\n          sliding + details.totalduration,\n        );\n        this.log(\n          `Start time offset ${startTimeOffset} found in ${\n            offsetInMultivariantPlaylist ? 'multivariant' : 'media'\n          } playlist, adjust startPosition to ${startPosition}`,\n        );\n        this.startPosition = startPosition;\n      } else if (details.live) {\n        // Leave this.startPosition at -1, so that we can use `getInitialLiveFragment` logic when startPosition has\n        // not been specified via the config or an as an argument to startLoad (#3736).\n        startPosition = this.hls.liveSyncPosition || sliding;\n      } else {\n        this.startPosition = startPosition = 0;\n      }\n      this.lastCurrentTime = startPosition;\n    }\n    this.nextLoadPosition = startPosition;\n  }\n\n  protected getLoadPosition(): number {\n    const { media } = this;\n    // if we have not yet loaded any fragment, start loading from start position\n    let pos = 0;\n    if (this.loadedmetadata && media) {\n      pos = media.currentTime;\n    } else if (this.nextLoadPosition) {\n      pos = this.nextLoadPosition;\n    }\n\n    return pos;\n  }\n\n  private handleFragLoadAborted(frag: Fragment, part: Part | undefined) {\n    if (this.transmuxer && frag.sn !== 'initSegment' && frag.stats.aborted) {\n      this.warn(\n        `Fragment ${frag.sn}${part ? ' part ' + part.index : ''} of level ${\n          frag.level\n        } was aborted`,\n      );\n      this.resetFragmentLoading(frag);\n    }\n  }\n\n  protected resetFragmentLoading(frag: Fragment) {\n    if (\n      !this.fragCurrent ||\n      (!this.fragContextChanged(frag) &&\n        this.state !== State.FRAG_LOADING_WAITING_RETRY)\n    ) {\n      this.state = State.IDLE;\n    }\n  }\n\n  protected onFragmentOrKeyLoadError(\n    filterType: PlaylistLevelType,\n    data: ErrorData,\n  ) {\n    if (data.chunkMeta && !data.frag) {\n      const context = this.getCurrentContext(data.chunkMeta);\n      if (context) {\n        data.frag = context.frag;\n      }\n    }\n    const frag = data.frag;\n    // Handle frag error related to caller's filterType\n    if (!frag || frag.type !== filterType || !this.levels) {\n      return;\n    }\n    if (this.fragContextChanged(frag)) {\n      this.warn(\n        `Frag load error must match current frag to retry ${frag.url} > ${this.fragCurrent?.url}`,\n      );\n      return;\n    }\n    const gapTagEncountered = data.details === ErrorDetails.FRAG_GAP;\n    if (gapTagEncountered) {\n      this.fragmentTracker.fragBuffered(frag, true);\n    }\n    // keep retrying until the limit will be reached\n    const errorAction = data.errorAction;\n    const { action, retryCount = 0, retryConfig } = errorAction || {};\n    if (\n      errorAction &&\n      action === NetworkErrorAction.RetryRequest &&\n      retryConfig\n    ) {\n      this.resetStartWhenNotLoaded(this.levelLastLoaded);\n      const delay = getRetryDelay(retryConfig, retryCount);\n      this.warn(\n        `Fragment ${frag.sn} of ${filterType} ${frag.level} errored with ${\n          data.details\n        }, retrying loading ${retryCount + 1}/${\n          retryConfig.maxNumRetry\n        } in ${delay}ms`,\n      );\n      errorAction.resolved = true;\n      this.retryDate = self.performance.now() + delay;\n      this.state = State.FRAG_LOADING_WAITING_RETRY;\n    } else if (retryConfig && errorAction) {\n      this.resetFragmentErrors(filterType);\n      if (retryCount < retryConfig.maxNumRetry) {\n        // Network retry is skipped when level switch is preferred\n        if (\n          !gapTagEncountered &&\n          action !== NetworkErrorAction.RemoveAlternatePermanently\n        ) {\n          errorAction.resolved = true;\n        }\n      } else {\n        logger.warn(\n          `${data.details} reached or exceeded max retry (${retryCount})`,\n        );\n        return;\n      }\n    } else if (\n      errorAction?.action === NetworkErrorAction.SendAlternateToPenaltyBox\n    ) {\n      this.state = State.WAITING_LEVEL;\n    } else {\n      this.state = State.ERROR;\n    }\n    // Perform next async tick sooner to speed up error action resolution\n    this.tickImmediate();\n  }\n\n  protected reduceLengthAndFlushBuffer(data: ErrorData): boolean {\n    // if in appending state\n    if (this.state === State.PARSING || this.state === State.PARSED) {\n      const frag = data.frag;\n      const playlistType = data.parent as PlaylistLevelType;\n      const bufferedInfo = this.getFwdBufferInfo(\n        this.mediaBuffer,\n        playlistType,\n      );\n      // 0.5 : tolerance needed as some browsers stalls playback before reaching buffered end\n      // reduce max buf len if current position is buffered\n      const buffered = bufferedInfo && bufferedInfo.len > 0.5;\n      if (buffered) {\n        this.reduceMaxBufferLength(bufferedInfo.len, frag?.duration || 10);\n      }\n      const flushBuffer = !buffered;\n      if (flushBuffer) {\n        // current position is not buffered, but browser is still complaining about buffer full error\n        // this happens on IE/Edge, refer to https://github.com/video-dev/hls.js/pull/708\n        // in that case flush the whole audio buffer to recover\n        this.warn(\n          `Buffer full error while media.currentTime is not buffered, flush ${playlistType} buffer`,\n        );\n      }\n      if (frag) {\n        this.fragmentTracker.removeFragment(frag);\n        this.nextLoadPosition = frag.start;\n      }\n      this.resetLoadingState();\n      return flushBuffer;\n    }\n    return false;\n  }\n\n  protected resetFragmentErrors(filterType: PlaylistLevelType) {\n    if (filterType === PlaylistLevelType.AUDIO) {\n      // Reset current fragment since audio track audio is essential and may not have a fail-over track\n      this.fragCurrent = null;\n    }\n    // Fragment errors that result in a level switch or redundant fail-over\n    // should reset the stream controller state to idle\n    if (!this.loadedmetadata) {\n      this.startFragRequested = false;\n    }\n    if (this.state !== State.STOPPED) {\n      this.state = State.IDLE;\n    }\n  }\n\n  protected afterBufferFlushed(\n    media: Bufferable,\n    bufferType: SourceBufferName,\n    playlistType: PlaylistLevelType,\n  ) {\n    if (!media) {\n      return;\n    }\n    // After successful buffer flushing, filter flushed fragments from bufferedFrags use mediaBuffered instead of media\n    // (so that we will check against video.buffered ranges in case of alt audio track)\n    const bufferedTimeRanges = BufferHelper.getBuffered(media);\n    this.fragmentTracker.detectEvictedFragments(\n      bufferType,\n      bufferedTimeRanges,\n      playlistType,\n    );\n    if (this.state === State.ENDED) {\n      this.resetLoadingState();\n    }\n  }\n\n  protected resetLoadingState() {\n    this.log('Reset loading state');\n    this.fragCurrent = null;\n    this.fragPrevious = null;\n    this.state = State.IDLE;\n  }\n\n  protected resetStartWhenNotLoaded(level: Level | null): void {\n    // if loadedmetadata is not set, it means that first frag request failed\n    // in that case, reset startFragRequested flag\n    if (!this.loadedmetadata) {\n      this.startFragRequested = false;\n      const details = level ? level.details : null;\n      if (details?.live) {\n        // Update the start position and return to IDLE to recover live start\n        this.startPosition = -1;\n        this.setStartPosition(details, 0);\n        this.resetLoadingState();\n      } else {\n        this.nextLoadPosition = this.startPosition;\n      }\n    }\n  }\n\n  protected resetWhenMissingContext(chunkMeta: ChunkMetadata) {\n    this.warn(\n      `The loading context changed while buffering fragment ${chunkMeta.sn} of level ${chunkMeta.level}. This chunk will not be buffered.`,\n    );\n    this.removeUnbufferedFrags();\n    this.resetStartWhenNotLoaded(this.levelLastLoaded);\n    this.resetLoadingState();\n  }\n\n  protected removeUnbufferedFrags(start: number = 0) {\n    this.fragmentTracker.removeFragmentsInRange(\n      start,\n      Infinity,\n      this.playlistType,\n      false,\n      true,\n    );\n  }\n\n  private updateLevelTiming(\n    frag: Fragment,\n    part: Part | null,\n    level: Level,\n    partial: boolean,\n  ) {\n    const details = level.details as LevelDetails;\n    if (!details) {\n      this.warn('level.details undefined');\n      return;\n    }\n    const parsed = Object.keys(frag.elementaryStreams).reduce(\n      (result, type) => {\n        const info = frag.elementaryStreams[type];\n        if (info) {\n          const parsedDuration = info.endPTS - info.startPTS;\n          if (parsedDuration <= 0) {\n            // Destroy the transmuxer after it's next time offset failed to advance because duration was <= 0.\n            // The new transmuxer will be configured with a time offset matching the next fragment start,\n            // preventing the timeline from shifting.\n            this.warn(\n              `Could not parse fragment ${frag.sn} ${type} duration reliably (${parsedDuration})`,\n            );\n            return result || false;\n          }\n          const drift = partial\n            ? 0\n            : updateFragPTSDTS(\n                details,\n                frag,\n                info.startPTS,\n                info.endPTS,\n                info.startDTS,\n                info.endDTS,\n              );\n          this.hls.trigger(Events.LEVEL_PTS_UPDATED, {\n            details,\n            level,\n            drift,\n            type,\n            frag,\n            start: info.startPTS,\n            end: info.endPTS,\n          });\n          return true;\n        }\n        return result;\n      },\n      false,\n    );\n    if (!parsed && this.transmuxer?.error === null) {\n      const error = new Error(\n        `Found no media in fragment ${frag.sn} of level ${frag.level} resetting transmuxer to fallback to playlist timing`,\n      );\n      if (level.fragmentError === 0) {\n        // Mark and track the odd empty segment as a gap to avoid reloading\n        level.fragmentError++;\n        frag.gap = true;\n        this.fragmentTracker.removeFragment(frag);\n        this.fragmentTracker.fragBuffered(frag, true);\n      }\n      this.warn(error.message);\n      this.hls.trigger(Events.ERROR, {\n        type: ErrorTypes.MEDIA_ERROR,\n        details: ErrorDetails.FRAG_PARSING_ERROR,\n        fatal: false,\n        error,\n        frag,\n        reason: `Found no media in msn ${frag.sn} of level \"${level.url}\"`,\n      });\n      if (!this.hls) {\n        return;\n      }\n      this.resetTransmuxer();\n      // For this error fallthrough. Marking parsed will allow advancing to next fragment.\n    }\n    this.state = State.PARSED;\n    this.hls.trigger(Events.FRAG_PARSED, { frag, part });\n  }\n\n  protected resetTransmuxer() {\n    if (this.transmuxer) {\n      this.transmuxer.destroy();\n      this.transmuxer = null;\n    }\n  }\n\n  protected recoverWorkerError(data: ErrorData) {\n    if (data.event === 'demuxerWorker') {\n      this.fragmentTracker.removeAllFragments();\n      this.resetTransmuxer();\n      this.resetStartWhenNotLoaded(this.levelLastLoaded);\n      this.resetLoadingState();\n    }\n  }\n\n  set state(nextState) {\n    const previousState = this._state;\n    if (previousState !== nextState) {\n      this._state = nextState;\n      this.log(`${previousState}->${nextState}`);\n    }\n  }\n\n  get state() {\n    return this._state;\n  }\n}\n", "export default class ChunkCache {\n  private chunks: Array<Uint8Array> = [];\n  public dataLength: number = 0;\n\n  push(chunk: Uint8Array) {\n    this.chunks.push(chunk);\n    this.dataLength += chunk.length;\n  }\n\n  flush(): Uint8Array {\n    const { chunks, dataLength } = this;\n    let result;\n    if (!chunks.length) {\n      return new Uint8Array(0);\n    } else if (chunks.length === 1) {\n      result = chunks[0];\n    } else {\n      result = concatUint8Arrays(chunks, dataLength);\n    }\n    this.reset();\n    return result;\n  }\n\n  reset() {\n    this.chunks.length = 0;\n    this.dataLength = 0;\n  }\n}\n\nfunction concatUint8Arrays(\n  chunks: Array<Uint8Array>,\n  dataLength: number,\n): Uint8Array {\n  const result = new Uint8Array(dataLength);\n  let offset = 0;\n  for (let i = 0; i < chunks.length; i++) {\n    const chunk = chunks[i];\n    result.set(chunk, offset);\n    offset += chunk.length;\n  }\n  return result;\n}\n", "// ensure the worker ends up in the bundle\n// If the worker should not be included this gets aliased to empty.js\nimport './transmuxer-worker';\n\nexport function hasUMDWorker(): boolean {\n  return typeof __HLS_WORKER_BUNDLE__ === 'function';\n}\n\nexport type WorkerContext = {\n  worker: Worker;\n  objectURL?: string;\n  scriptURL?: string;\n};\n\nexport function injectWorker(): WorkerContext {\n  const blob = new self.Blob(\n    [\n      `var exports={};var module={exports:exports};function define(f){f()};define.amd=true;(${__HLS_WORKER_BUNDLE__.toString()})(true);`,\n    ],\n    {\n      type: 'text/javascript',\n    },\n  );\n  const objectURL = self.URL.createObjectURL(blob);\n  const worker = new self.Worker(objectURL);\n\n  return {\n    worker,\n    objectURL,\n  };\n}\n\nexport function loadWorker(path: string): WorkerContext {\n  const scriptURL = new self.URL(path, self.location.href).href;\n  const worker = new self.Worker(scriptURL);\n\n  return {\n    worker,\n    scriptURL,\n  };\n}\n", "import type { DemuxedTrack } from '../types/demuxer';\n\nexport function dummyTrack(type = '', inputTimeScale = 90000): DemuxedTrack {\n  return {\n    type,\n    id: -1,\n    pid: -1,\n    inputTimeScale,\n    sequenceNumber: -1,\n    samples: [],\n    dropped: 0,\n  };\n}\n", "import * as ID3 from '../id3';\nimport {\n  DemuxerResult,\n  Demuxer,\n  DemuxedAudioTrack,\n  AudioFrame,\n  DemuxedMetadataTrack,\n  DemuxedVideoTrackBase,\n  DemuxedUserdataTrack,\n  KeyData,\n  MetadataSchema,\n} from '../../types/demuxer';\nimport { dummyTrack } from '../dummy-demuxed-track';\nimport { appendUint8Array } from '../../utils/mp4-tools';\nimport { sliceUint8 } from '../../utils/typed-array';\nimport { RationalTimestamp } from '../../utils/timescale-conversion';\n\nclass BaseAudioDemuxer implements Demuxer {\n  protected _audioTrack!: DemuxedAudioTrack;\n  protected _id3Track!: DemuxedMetadataTrack;\n  protected frameIndex: number = 0;\n  protected cachedData: Uint8Array | null = null;\n  protected basePTS: number | null = null;\n  protected initPTS: RationalTimestamp | null = null;\n  protected lastPTS: number | null = null;\n\n  resetInitSegment(\n    initSegment: Uint8Array | undefined,\n    audioCodec: string | undefined,\n    videoCodec: string | undefined,\n    trackDuration: number,\n  ) {\n    this._id3Track = {\n      type: 'id3',\n      id: 3,\n      pid: -1,\n      inputTimeScale: 90000,\n      sequenceNumber: 0,\n      samples: [],\n      dropped: 0,\n    };\n  }\n\n  resetTimeStamp(deaultTimestamp: RationalTimestamp | null) {\n    this.initPTS = deaultTimestamp;\n    this.resetContiguity();\n  }\n\n  resetContiguity(): void {\n    this.basePTS = null;\n    this.lastPTS = null;\n    this.frameIndex = 0;\n  }\n\n  canParse(data: Uint8Array, offset: number): boolean {\n    return false;\n  }\n\n  appendFrame(\n    track: DemuxedAudioTrack,\n    data: Uint8Array,\n    offset: number,\n  ): AudioFrame | void {}\n\n  // feed incoming data to the front of the parsing pipeline\n  demux(data: Uint8Array, timeOffset: number): DemuxerResult {\n    if (this.cachedData) {\n      data = appendUint8Array(this.cachedData, data);\n      this.cachedData = null;\n    }\n\n    let id3Data: Uint8Array | undefined = ID3.getID3Data(data, 0);\n    let offset = id3Data ? id3Data.length : 0;\n    let lastDataIndex;\n    const track = this._audioTrack;\n    const id3Track = this._id3Track;\n    const timestamp = id3Data ? ID3.getTimeStamp(id3Data) : undefined;\n    const length = data.length;\n\n    if (\n      this.basePTS === null ||\n      (this.frameIndex === 0 && Number.isFinite(timestamp))\n    ) {\n      this.basePTS = initPTSFn(timestamp, timeOffset, this.initPTS);\n      this.lastPTS = this.basePTS;\n    }\n\n    if (this.lastPTS === null) {\n      this.lastPTS = this.basePTS;\n    }\n\n    // more expressive than alternative: id3Data?.length\n    if (id3Data && id3Data.length > 0) {\n      id3Track.samples.push({\n        pts: this.lastPTS,\n        dts: this.lastPTS,\n        data: id3Data,\n        type: MetadataSchema.audioId3,\n        duration: Number.POSITIVE_INFINITY,\n      });\n    }\n\n    while (offset < length) {\n      if (this.canParse(data, offset)) {\n        const frame = this.appendFrame(track, data, offset);\n        if (frame) {\n          this.frameIndex++;\n          this.lastPTS = frame.sample.pts;\n          offset += frame.length;\n          lastDataIndex = offset;\n        } else {\n          offset = length;\n        }\n      } else if (ID3.canParse(data, offset)) {\n        // after a ID3.canParse, a call to ID3.getID3Data *should* always returns some data\n        id3Data = ID3.getID3Data(data, offset)!;\n        id3Track.samples.push({\n          pts: this.lastPTS,\n          dts: this.lastPTS,\n          data: id3Data,\n          type: MetadataSchema.audioId3,\n          duration: Number.POSITIVE_INFINITY,\n        });\n        offset += id3Data.length;\n        lastDataIndex = offset;\n      } else {\n        offset++;\n      }\n      if (offset === length && lastDataIndex !== length) {\n        const partialData = sliceUint8(data, lastDataIndex);\n        if (this.cachedData) {\n          this.cachedData = appendUint8Array(this.cachedData, partialData);\n        } else {\n          this.cachedData = partialData;\n        }\n      }\n    }\n\n    return {\n      audioTrack: track,\n      videoTrack: dummyTrack() as DemuxedVideoTrackBase,\n      id3Track,\n      textTrack: dummyTrack() as DemuxedUserdataTrack,\n    };\n  }\n\n  demuxSampleAes(\n    data: Uint8Array,\n    keyData: KeyData,\n    timeOffset: number,\n  ): Promise<DemuxerResult> {\n    return Promise.reject(\n      new Error(\n        `[${this}] This demuxer does not support Sample-AES decryption`,\n      ),\n    );\n  }\n\n  flush(timeOffset: number): DemuxerResult {\n    // Parse cache in case of remaining frames.\n    const cachedData = this.cachedData;\n    if (cachedData) {\n      this.cachedData = null;\n      this.demux(cachedData, 0);\n    }\n\n    return {\n      audioTrack: this._audioTrack,\n      videoTrack: dummyTrack() as DemuxedVideoTrackBase,\n      id3Track: this._id3Track,\n      textTrack: dummyTrack() as DemuxedUserdataTrack,\n    };\n  }\n\n  destroy() {}\n}\n\n/**\n * Initialize PTS\n * <p>\n *    use timestamp unless it is undefined, NaN or Infinity\n * </p>\n */\nexport const initPTSFn = (\n  timestamp: number | undefined,\n  timeOffset: number,\n  initPTS: RationalTimestamp | null,\n): number => {\n  if (Number.isFinite(timestamp as number)) {\n    return timestamp! * 90;\n  }\n  const init90kHz = initPTS\n    ? (initPTS.baseTime * 90000) / initPTS.timescale\n    : 0;\n  return timeOffset * 90000 + init90kHz;\n};\nexport default BaseAudioDemuxer;\n", "/**\n * ADTS parser helper\n * @link https://wiki.multimedia.cx/index.php?title=ADTS\n */\nimport { logger } from '../../utils/logger';\nimport { ErrorTypes, ErrorDetails } from '../../errors';\nimport type { HlsEventEmitter } from '../../events';\nimport { Events } from '../../events';\nimport type {\n  DemuxedAudioTrack,\n  AudioFrame,\n  AudioSample,\n} from '../../types/demuxer';\n\ntype AudioConfig = {\n  config: number[];\n  samplerate: number;\n  channelCount: number;\n  codec: string;\n  manifestCodec: string;\n};\n\ntype FrameHeader = {\n  headerLength: number;\n  frameLength: number;\n};\n\nexport function getAudioConfig(\n  observer: HlsEventEmitter,\n  data: Uint8Array,\n  offset: number,\n  audioCodec: string,\n): AudioConfig | void {\n  let adtsObjectType: number;\n  let adtsExtensionSamplingIndex: number;\n  let adtsChannelConfig: number;\n  let config: number[];\n  const userAgent = navigator.userAgent.toLowerCase();\n  const manifestCodec = audioCodec;\n  const adtsSamplingRates = [\n    96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025,\n    8000, 7350,\n  ];\n  // byte 2\n  adtsObjectType = ((data[offset + 2] & 0xc0) >>> 6) + 1;\n  const adtsSamplingIndex = (data[offset + 2] & 0x3c) >>> 2;\n  if (adtsSamplingIndex > adtsSamplingRates.length - 1) {\n    const error = new Error(`invalid ADTS sampling index:${adtsSamplingIndex}`);\n    observer.emit(Events.ERROR, Events.ERROR, {\n      type: ErrorTypes.MEDIA_ERROR,\n      details: ErrorDetails.FRAG_PARSING_ERROR,\n      fatal: true,\n      error,\n      reason: error.message,\n    });\n    return;\n  }\n  adtsChannelConfig = (data[offset + 2] & 0x01) << 2;\n  // byte 3\n  adtsChannelConfig |= (data[offset + 3] & 0xc0) >>> 6;\n  logger.log(\n    `manifest codec:${audioCodec}, ADTS type:${adtsObjectType}, samplingIndex:${adtsSamplingIndex}`,\n  );\n  // firefox: freq less than 24kHz = AAC SBR (HE-AAC)\n  if (/firefox/i.test(userAgent)) {\n    if (adtsSamplingIndex >= 6) {\n      adtsObjectType = 5;\n      config = new Array(4);\n      // HE-AAC uses SBR (Spectral Band Replication) , high frequencies are constructed from low frequencies\n      // there is a factor 2 between frame sample rate and output sample rate\n      // multiply frequency by 2 (see table below, equivalent to substract 3)\n      adtsExtensionSamplingIndex = adtsSamplingIndex - 3;\n    } else {\n      adtsObjectType = 2;\n      config = new Array(2);\n      adtsExtensionSamplingIndex = adtsSamplingIndex;\n    }\n    // Android : always use AAC\n  } else if (userAgent.indexOf('android') !== -1) {\n    adtsObjectType = 2;\n    config = new Array(2);\n    adtsExtensionSamplingIndex = adtsSamplingIndex;\n  } else {\n    /*  for other browsers (Chrome/Vivaldi/Opera ...)\n        always force audio type to be HE-AAC SBR, as some browsers do not support audio codec switch properly (like Chrome ...)\n    */\n    adtsObjectType = 5;\n    config = new Array(4);\n    // if (manifest codec is HE-AAC or HE-AACv2) OR (manifest codec not specified AND frequency less than 24kHz)\n    if (\n      (audioCodec &&\n        (audioCodec.indexOf('mp4a.40.29') !== -1 ||\n          audioCodec.indexOf('mp4a.40.5') !== -1)) ||\n      (!audioCodec && adtsSamplingIndex >= 6)\n    ) {\n      // HE-AAC uses SBR (Spectral Band Replication) , high frequencies are constructed from low frequencies\n      // there is a factor 2 between frame sample rate and output sample rate\n      // multiply frequency by 2 (see table below, equivalent to substract 3)\n      adtsExtensionSamplingIndex = adtsSamplingIndex - 3;\n    } else {\n      // if (manifest codec is AAC) AND (frequency less than 24kHz AND nb channel is 1) OR (manifest codec not specified and mono audio)\n      // Chrome fails to play back with low frequency AAC LC mono when initialized with HE-AAC.  This is not a problem with stereo.\n      if (\n        (audioCodec &&\n          audioCodec.indexOf('mp4a.40.2') !== -1 &&\n          ((adtsSamplingIndex >= 6 && adtsChannelConfig === 1) ||\n            /vivaldi/i.test(userAgent))) ||\n        (!audioCodec && adtsChannelConfig === 1)\n      ) {\n        adtsObjectType = 2;\n        config = new Array(2);\n      }\n      adtsExtensionSamplingIndex = adtsSamplingIndex;\n    }\n  }\n  /* refer to http://wiki.multimedia.cx/index.php?title=MPEG-4_Audio#Audio_Specific_Config\n      ISO 14496-3 (AAC).pdf - Table 1.13 \u2014 Syntax of AudioSpecificConfig()\n    Audio Profile / Audio Object Type\n    0: Null\n    1: AAC Main\n    2: AAC LC (Low Complexity)\n    3: AAC SSR (Scalable Sample Rate)\n    4: AAC LTP (Long Term Prediction)\n    5: SBR (Spectral Band Replication)\n    6: AAC Scalable\n   sampling freq\n    0: 96000 Hz\n    1: 88200 Hz\n    2: 64000 Hz\n    3: 48000 Hz\n    4: 44100 Hz\n    5: 32000 Hz\n    6: 24000 Hz\n    7: 22050 Hz\n    8: 16000 Hz\n    9: 12000 Hz\n    10: 11025 Hz\n    11: 8000 Hz\n    12: 7350 Hz\n    13: Reserved\n    14: Reserved\n    15: frequency is written explictly\n    Channel Configurations\n    These are the channel configurations:\n    0: Defined in AOT Specifc Config\n    1: 1 channel: front-center\n    2: 2 channels: front-left, front-right\n  */\n  // audioObjectType = profile => profile, the MPEG-4 Audio Object Type minus 1\n  config[0] = adtsObjectType << 3;\n  // samplingFrequencyIndex\n  config[0] |= (adtsSamplingIndex & 0x0e) >> 1;\n  config[1] |= (adtsSamplingIndex & 0x01) << 7;\n  // channelConfiguration\n  config[1] |= adtsChannelConfig << 3;\n  if (adtsObjectType === 5) {\n    // adtsExtensionSamplingIndex\n    config[1] |= (adtsExtensionSamplingIndex & 0x0e) >> 1;\n    config[2] = (adtsExtensionSamplingIndex & 0x01) << 7;\n    // adtsObjectType (force to 2, chrome is checking that object type is less than 5 ???\n    //    https://chromium.googlesource.com/chromium/src.git/+/master/media/formats/mp4/aac.cc\n    config[2] |= 2 << 2;\n    config[3] = 0;\n  }\n  return {\n    config,\n    samplerate: adtsSamplingRates[adtsSamplingIndex],\n    channelCount: adtsChannelConfig,\n    codec: 'mp4a.40.' + adtsObjectType,\n    manifestCodec,\n  };\n}\n\nexport function isHeaderPattern(data: Uint8Array, offset: number): boolean {\n  return data[offset] === 0xff && (data[offset + 1] & 0xf6) === 0xf0;\n}\n\nexport function getHeaderLength(data: Uint8Array, offset: number): number {\n  return data[offset + 1] & 0x01 ? 7 : 9;\n}\n\nexport function getFullFrameLength(data: Uint8Array, offset: number): number {\n  return (\n    ((data[offset + 3] & 0x03) << 11) |\n    (data[offset + 4] << 3) |\n    ((data[offset + 5] & 0xe0) >>> 5)\n  );\n}\n\nexport function canGetFrameLength(data: Uint8Array, offset: number): boolean {\n  return offset + 5 < data.length;\n}\n\nexport function isHeader(data: Uint8Array, offset: number): boolean {\n  // Look for ADTS header | 1111 1111 | 1111 X00X | where X can be either 0 or 1\n  // Layer bits (position 14 and 15) in header should be always 0 for ADTS\n  // More info https://wiki.multimedia.cx/index.php?title=ADTS\n  return offset + 1 < data.length && isHeaderPattern(data, offset);\n}\n\nexport function canParse(data: Uint8Array, offset: number): boolean {\n  return (\n    canGetFrameLength(data, offset) &&\n    isHeaderPattern(data, offset) &&\n    getFullFrameLength(data, offset) <= data.length - offset\n  );\n}\n\nexport function probe(data: Uint8Array, offset: number): boolean {\n  // same as isHeader but we also check that ADTS frame follows last ADTS frame\n  // or end of data is reached\n  if (isHeader(data, offset)) {\n    // ADTS header Length\n    const headerLength = getHeaderLength(data, offset);\n    if (offset + headerLength >= data.length) {\n      return false;\n    }\n    // ADTS frame Length\n    const frameLength = getFullFrameLength(data, offset);\n    if (frameLength <= headerLength) {\n      return false;\n    }\n\n    const newOffset = offset + frameLength;\n    return newOffset === data.length || isHeader(data, newOffset);\n  }\n  return false;\n}\n\nexport function initTrackConfig(\n  track: DemuxedAudioTrack,\n  observer: HlsEventEmitter,\n  data: Uint8Array,\n  offset: number,\n  audioCodec: string,\n) {\n  if (!track.samplerate) {\n    const config = getAudioConfig(observer, data, offset, audioCodec);\n    if (!config) {\n      return;\n    }\n    track.config = config.config;\n    track.samplerate = config.samplerate;\n    track.channelCount = config.channelCount;\n    track.codec = config.codec;\n    track.manifestCodec = config.manifestCodec;\n    logger.log(\n      `parsed codec:${track.codec}, rate:${config.samplerate}, channels:${config.channelCount}`,\n    );\n  }\n}\n\nexport function getFrameDuration(samplerate: number): number {\n  return (1024 * 90000) / samplerate;\n}\n\nexport function parseFrameHeader(\n  data: Uint8Array,\n  offset: number,\n): FrameHeader | void {\n  // The protection skip bit tells us if we have 2 bytes of CRC data at the end of the ADTS header\n  const headerLength = getHeaderLength(data, offset);\n  if (offset + headerLength <= data.length) {\n    // retrieve frame size\n    const frameLength = getFullFrameLength(data, offset) - headerLength;\n    if (frameLength > 0) {\n      // logger.log(`AAC frame, offset/length/total/pts:${offset+headerLength}/${frameLength}/${data.byteLength}`);\n      return { headerLength, frameLength };\n    }\n  }\n}\n\nexport function appendFrame(\n  track: DemuxedAudioTrack,\n  data: Uint8Array,\n  offset: number,\n  pts: number,\n  frameIndex: number,\n): AudioFrame {\n  const frameDuration = getFrameDuration(track.samplerate as number);\n  const stamp = pts + frameIndex * frameDuration;\n  const header = parseFrameHeader(data, offset);\n  let unit: Uint8Array;\n  if (header) {\n    const { frameLength, headerLength } = header;\n    const length = headerLength + frameLength;\n    const missing = Math.max(0, offset + length - data.length);\n    // logger.log(`AAC frame ${frameIndex}, pts:${stamp} length@offset/total: ${frameLength}@${offset+headerLength}/${data.byteLength} missing: ${missing}`);\n    if (missing) {\n      unit = new Uint8Array(length - headerLength);\n      unit.set(data.subarray(offset + headerLength, data.length), 0);\n    } else {\n      unit = data.subarray(offset + headerLength, offset + length);\n    }\n\n    const sample: AudioSample = {\n      unit,\n      pts: stamp,\n    };\n    if (!missing) {\n      track.samples.push(sample as AudioSample);\n    }\n\n    return { sample, length, missing };\n  }\n  // overflow incomplete header\n  const length = data.length - offset;\n  unit = new Uint8Array(length);\n  unit.set(data.subarray(offset, data.length), 0);\n  const sample: AudioSample = {\n    unit,\n    pts: stamp,\n  };\n  return { sample, length, missing: -1 };\n}\n", "/**\n *  MPEG parser helper\n */\nimport { DemuxedAudioTrack } from '../../types/demuxer';\n\nlet chromeVersion: number | null = null;\n\nconst BitratesMap = [\n  32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 32, 48, 56,\n  64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 32, 40, 48, 56, 64, 80,\n  96, 112, 128, 160, 192, 224, 256, 320, 32, 48, 56, 64, 80, 96, 112, 128, 144,\n  160, 176, 192, 224, 256, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144,\n  160,\n];\n\nconst SamplingRateMap = [\n  44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000,\n];\n\nconst SamplesCoefficients = [\n  // MPEG 2.5\n  [\n    0, // Reserved\n    72, // Layer3\n    144, // Layer2\n    12, // Layer1\n  ],\n  // Reserved\n  [\n    0, // Reserved\n    0, // Layer3\n    0, // Layer2\n    0, // Layer1\n  ],\n  // MPEG 2\n  [\n    0, // Reserved\n    72, // Layer3\n    144, // Layer2\n    12, // Layer1\n  ],\n  // MPEG 1\n  [\n    0, // Reserved\n    144, // Layer3\n    144, // Layer2\n    12, // Layer1\n  ],\n];\n\nconst BytesInSlot = [\n  0, // Reserved\n  1, // Layer3\n  1, // Layer2\n  4, // Layer1\n];\n\nexport function appendFrame(\n  track: DemuxedAudioTrack,\n  data: Uint8Array,\n  offset: number,\n  pts: number,\n  frameIndex: number,\n) {\n  // Using http://www.datavoyage.com/mpgscript/mpeghdr.htm as a reference\n  if (offset + 24 > data.length) {\n    return;\n  }\n\n  const header = parseHeader(data, offset);\n  if (header && offset + header.frameLength <= data.length) {\n    const frameDuration = (header.samplesPerFrame * 90000) / header.sampleRate;\n    const stamp = pts + frameIndex * frameDuration;\n    const sample = {\n      unit: data.subarray(offset, offset + header.frameLength),\n      pts: stamp,\n      dts: stamp,\n    };\n\n    track.config = [];\n    track.channelCount = header.channelCount;\n    track.samplerate = header.sampleRate;\n    track.samples.push(sample);\n\n    return { sample, length: header.frameLength, missing: 0 };\n  }\n}\n\nexport function parseHeader(data: Uint8Array, offset: number) {\n  const mpegVersion = (data[offset + 1] >> 3) & 3;\n  const mpegLayer = (data[offset + 1] >> 1) & 3;\n  const bitRateIndex = (data[offset + 2] >> 4) & 15;\n  const sampleRateIndex = (data[offset + 2] >> 2) & 3;\n  if (\n    mpegVersion !== 1 &&\n    bitRateIndex !== 0 &&\n    bitRateIndex !== 15 &&\n    sampleRateIndex !== 3\n  ) {\n    const paddingBit = (data[offset + 2] >> 1) & 1;\n    const channelMode = data[offset + 3] >> 6;\n    const columnInBitrates =\n      mpegVersion === 3 ? 3 - mpegLayer : mpegLayer === 3 ? 3 : 4;\n    const bitRate =\n      BitratesMap[columnInBitrates * 14 + bitRateIndex - 1] * 1000;\n    const columnInSampleRates =\n      mpegVersion === 3 ? 0 : mpegVersion === 2 ? 1 : 2;\n    const sampleRate =\n      SamplingRateMap[columnInSampleRates * 3 + sampleRateIndex];\n    const channelCount = channelMode === 3 ? 1 : 2; // If bits of channel mode are `11` then it is a single channel (Mono)\n    const sampleCoefficient = SamplesCoefficients[mpegVersion][mpegLayer];\n    const bytesInSlot = BytesInSlot[mpegLayer];\n    const samplesPerFrame = sampleCoefficient * 8 * bytesInSlot;\n    const frameLength =\n      Math.floor((sampleCoefficient * bitRate) / sampleRate + paddingBit) *\n      bytesInSlot;\n\n    if (chromeVersion === null) {\n      const userAgent = navigator.userAgent || '';\n      const result = userAgent.match(/Chrome\\/(\\d+)/i);\n      chromeVersion = result ? parseInt(result[1]) : 0;\n    }\n    const needChromeFix = !!chromeVersion && chromeVersion <= 87;\n\n    if (\n      needChromeFix &&\n      mpegLayer === 2 &&\n      bitRate >= 224000 &&\n      channelMode === 0\n    ) {\n      // Work around bug in Chromium by setting channelMode to dual-channel (01) instead of stereo (00)\n      data[offset + 3] = data[offset + 3] | 0x80;\n    }\n\n    return { sampleRate, channelCount, frameLength, samplesPerFrame };\n  }\n}\n\nexport function isHeaderPattern(data: Uint8Array, offset: number): boolean {\n  return (\n    data[offset] === 0xff &&\n    (data[offset + 1] & 0xe0) === 0xe0 &&\n    (data[offset + 1] & 0x06) !== 0x00\n  );\n}\n\nexport function isHeader(data: Uint8Array, offset: number): boolean {\n  // Look for MPEG header | 1111 1111 | 111X XYZX | where X can be either 0 or 1 and Y or Z should be 1\n  // Layer bits (position 14 and 15) in header should be always different from 0 (Layer I or Layer II or Layer III)\n  // More info http://www.mp3-tech.org/programmer/frame_header.html\n  return offset + 1 < data.length && isHeaderPattern(data, offset);\n}\n\nexport function canParse(data: Uint8Array, offset: number): boolean {\n  const headerSize = 4;\n\n  return isHeaderPattern(data, offset) && headerSize <= data.length - offset;\n}\n\nexport function probe(data: Uint8Array, offset: number): boolean {\n  // same as isHeader but we also check that MPEG frame follows last MPEG frame\n  // or end of data is reached\n  if (offset + 1 < data.length && isHeaderPattern(data, offset)) {\n    // MPEG header Length\n    const headerLength = 4;\n    // MPEG frame Length\n    const header = parseHeader(data, offset);\n    let frameLength = headerLength;\n    if (header?.frameLength) {\n      frameLength = header.frameLength;\n    }\n\n    const newOffset = offset + frameLength;\n    return newOffset === data.length || isHeader(data, newOffset);\n  }\n  return false;\n}\n", "/**\n * AAC demuxer\n */\nimport BaseAudioDemuxer from './base-audio-demuxer';\nimport * as ADTS from './adts';\nimport * as MpegAudio from './mpegaudio';\nimport { logger } from '../../utils/logger';\nimport * as ID3 from '../id3';\nimport type { HlsEventEmitter } from '../../events';\nimport type { HlsConfig } from '../../config';\n\nclass AACDemuxer extends BaseAudioDemuxer {\n  private readonly observer: HlsEventEmitter;\n  private readonly config: HlsConfig;\n\n  constructor(observer, config) {\n    super();\n    this.observer = observer;\n    this.config = config;\n  }\n\n  resetInitSegment(\n    initSegment: Uint8Array | undefined,\n    audioCodec: string | undefined,\n    videoCodec: string | undefined,\n    trackDuration: number,\n  ) {\n    super.resetInitSegment(initSegment, audioCodec, videoCodec, trackDuration);\n    this._audioTrack = {\n      container: 'audio/adts',\n      type: 'audio',\n      id: 2,\n      pid: -1,\n      sequenceNumber: 0,\n      segmentCodec: 'aac',\n      samples: [],\n      manifestCodec: audioCodec,\n      duration: trackDuration,\n      inputTimeScale: 90000,\n      dropped: 0,\n    };\n  }\n\n  // Source for probe info - https://wiki.multimedia.cx/index.php?title=ADTS\n  static probe(data: Uint8Array | undefined): boolean {\n    if (!data) {\n      return false;\n    }\n\n    // Check for the ADTS sync word\n    // Look for ADTS header | 1111 1111 | 1111 X00X | where X can be either 0 or 1\n    // Layer bits (position 14 and 15) in header should be always 0 for ADTS\n    // More info https://wiki.multimedia.cx/index.php?title=ADTS\n    const id3Data = ID3.getID3Data(data, 0);\n    let offset = id3Data?.length || 0;\n\n    if (MpegAudio.probe(data, offset)) {\n      return false;\n    }\n\n    for (let length = data.length; offset < length; offset++) {\n      if (ADTS.probe(data, offset)) {\n        logger.log('ADTS sync word found !');\n        return true;\n      }\n    }\n    return false;\n  }\n\n  canParse(data, offset) {\n    return ADTS.canParse(data, offset);\n  }\n\n  appendFrame(track, data, offset) {\n    ADTS.initTrackConfig(\n      track,\n      this.observer,\n      data,\n      offset,\n      track.manifestCodec,\n    );\n    const frame = ADTS.appendFrame(\n      track,\n      data,\n      offset,\n      this.basePTS as number,\n      this.frameIndex,\n    );\n    if (frame && frame.missing === 0) {\n      return frame;\n    }\n  }\n}\n\nexport default AACDemuxer;\n", "/**\n * MP4 demuxer\n */\nimport {\n  Demuxer,\n  DemuxerResult,\n  PassthroughTrack,\n  DemuxedAudioTrack,\n  DemuxedUserdataTrack,\n  DemuxedMetadataTrack,\n  KeyData,\n  MetadataSchema,\n} from '../types/demuxer';\nimport {\n  findBox,\n  segmentValidRange,\n  appendUint8Array,\n  parseEmsg,\n  parseSamples,\n  parseInitSegment,\n  RemuxerTrackIdConfig,\n  hasMoofData,\n} from '../utils/mp4-tools';\nimport { dummyTrack } from './dummy-demuxed-track';\nimport type { HlsEventEmitter } from '../events';\nimport type { HlsConfig } from '../config';\n\nconst emsgSchemePattern = /\\/emsg[-/]ID3/i;\n\nclass MP4Demuxer implements Demuxer {\n  private remainderData: Uint8Array | null = null;\n  private timeOffset: number = 0;\n  private config: HlsConfig;\n  private videoTrack?: PassthroughTrack;\n  private audioTrack?: DemuxedAudioTrack;\n  private id3Track?: DemuxedMetadataTrack;\n  private txtTrack?: DemuxedUserdataTrack;\n\n  constructor(observer: HlsEventEmitter, config: HlsConfig) {\n    this.config = config;\n  }\n\n  public resetTimeStamp() {}\n\n  public resetInitSegment(\n    initSegment: Uint8Array | undefined,\n    audioCodec: string | undefined,\n    videoCodec: string | undefined,\n    trackDuration: number,\n  ) {\n    const videoTrack = (this.videoTrack = dummyTrack(\n      'video',\n      1,\n    ) as PassthroughTrack);\n    const audioTrack = (this.audioTrack = dummyTrack(\n      'audio',\n      1,\n    ) as DemuxedAudioTrack);\n    const captionTrack = (this.txtTrack = dummyTrack(\n      'text',\n      1,\n    ) as DemuxedUserdataTrack);\n\n    this.id3Track = dummyTrack('id3', 1) as DemuxedMetadataTrack;\n    this.timeOffset = 0;\n\n    if (!initSegment?.byteLength) {\n      return;\n    }\n    const initData = parseInitSegment(initSegment);\n\n    if (initData.video) {\n      const { id, timescale, codec } = initData.video;\n      videoTrack.id = id;\n      videoTrack.timescale = captionTrack.timescale = timescale;\n      videoTrack.codec = codec;\n    }\n\n    if (initData.audio) {\n      const { id, timescale, codec } = initData.audio;\n      audioTrack.id = id;\n      audioTrack.timescale = timescale;\n      audioTrack.codec = codec;\n    }\n\n    captionTrack.id = RemuxerTrackIdConfig.text;\n    videoTrack.sampleDuration = 0;\n    videoTrack.duration = audioTrack.duration = trackDuration;\n  }\n\n  public resetContiguity(): void {\n    this.remainderData = null;\n  }\n\n  static probe(data: Uint8Array) {\n    return hasMoofData(data);\n  }\n\n  public demux(data: Uint8Array, timeOffset: number): DemuxerResult {\n    this.timeOffset = timeOffset;\n    // Load all data into the avc track. The CMAF remuxer will look for the data in the samples object; the rest of the fields do not matter\n    let videoSamples = data;\n    const videoTrack = this.videoTrack as PassthroughTrack;\n    const textTrack = this.txtTrack as DemuxedUserdataTrack;\n    if (this.config.progressive) {\n      // Split the bytestream into two ranges: one encompassing all data up until the start of the last moof, and everything else.\n      // This is done to guarantee that we're sending valid data to MSE - when demuxing progressively, we have no guarantee\n      // that the fetch loader gives us flush moof+mdat pairs. If we push jagged data to MSE, it will throw an exception.\n      if (this.remainderData) {\n        videoSamples = appendUint8Array(this.remainderData, data);\n      }\n      const segmentedData = segmentValidRange(videoSamples);\n      this.remainderData = segmentedData.remainder;\n      videoTrack.samples = segmentedData.valid || new Uint8Array();\n    } else {\n      videoTrack.samples = videoSamples;\n    }\n\n    const id3Track = this.extractID3Track(videoTrack, timeOffset);\n    textTrack.samples = parseSamples(timeOffset, videoTrack);\n\n    return {\n      videoTrack,\n      audioTrack: this.audioTrack as DemuxedAudioTrack,\n      id3Track,\n      textTrack: this.txtTrack as DemuxedUserdataTrack,\n    };\n  }\n\n  public flush() {\n    const timeOffset = this.timeOffset;\n    const videoTrack = this.videoTrack as PassthroughTrack;\n    const textTrack = this.txtTrack as DemuxedUserdataTrack;\n    videoTrack.samples = this.remainderData || new Uint8Array();\n    this.remainderData = null;\n\n    const id3Track = this.extractID3Track(videoTrack, this.timeOffset);\n    textTrack.samples = parseSamples(timeOffset, videoTrack);\n\n    return {\n      videoTrack,\n      audioTrack: dummyTrack() as DemuxedAudioTrack,\n      id3Track,\n      textTrack: dummyTrack() as DemuxedUserdataTrack,\n    };\n  }\n\n  private extractID3Track(\n    videoTrack: PassthroughTrack,\n    timeOffset: number,\n  ): DemuxedMetadataTrack {\n    const id3Track = this.id3Track as DemuxedMetadataTrack;\n    if (videoTrack.samples.length) {\n      const emsgs = findBox(videoTrack.samples, ['emsg']);\n      if (emsgs) {\n        emsgs.forEach((data: Uint8Array) => {\n          const emsgInfo = parseEmsg(data);\n          if (emsgSchemePattern.test(emsgInfo.schemeIdUri)) {\n            const pts = Number.isFinite(emsgInfo.presentationTime)\n              ? emsgInfo.presentationTime! / emsgInfo.timeScale\n              : timeOffset +\n                emsgInfo.presentationTimeDelta! / emsgInfo.timeScale;\n            let duration =\n              emsgInfo.eventDuration === 0xffffffff\n                ? Number.POSITIVE_INFINITY\n                : emsgInfo.eventDuration / emsgInfo.timeScale;\n            // Safari takes anything <= 0.001 seconds and maps it to Infinity\n            if (duration <= 0.001) {\n              duration = Number.POSITIVE_INFINITY;\n            }\n            const payload = emsgInfo.payload;\n            id3Track.samples.push({\n              data: payload,\n              len: payload.byteLength,\n              dts: pts,\n              pts: pts,\n              type: MetadataSchema.emsg,\n              duration: duration,\n            });\n          }\n        });\n      }\n    }\n    return id3Track;\n  }\n\n  demuxSampleAes(\n    data: Uint8Array,\n    keyData: KeyData,\n    timeOffset: number,\n  ): Promise<DemuxerResult> {\n    return Promise.reject(\n      new Error('The MP4 demuxer does not support SAMPLE-AES decryption'),\n    );\n  }\n\n  destroy() {}\n}\n\nexport default MP4Demuxer;\n", "export const getAudioBSID = (data: Uint8Array, offset: number): number => {\n  // check the bsid to confirm ac-3 | ec-3\n  let bsid = 0;\n  let numBits = 5;\n  offset += numBits;\n  const temp = new Uint32Array(1); // unsigned 32 bit for temporary storage\n  const mask = new Uint32Array(1); // unsigned 32 bit mask value\n  const byte = new Uint8Array(1); // unsigned 8 bit for temporary storage\n  while (numBits > 0) {\n    byte[0] = data[offset];\n    // read remaining bits, upto 8 bits at a time\n    const bits = Math.min(numBits, 8);\n    const shift = 8 - bits;\n    mask[0] = (0xff000000 >>> (24 + shift)) << shift;\n    temp[0] = (byte[0] & mask[0]) >> shift;\n    bsid = !bsid ? temp[0] : (bsid << bits) | temp[0];\n    offset += 1;\n    numBits -= bits;\n  }\n  return bsid;\n};\n", "import BaseAudioDemuxer from './base-audio-demuxer';\nimport { getID3Data, getTimeStamp } from '../id3';\nimport { getAudioBSID } from './dolby';\nimport type { HlsEventEmitter } from '../../events';\nimport type { AudioFrame, DemuxedAudioTrack } from '../../types/demuxer';\n\nexport class AC3Demuxer extends BaseAudioDemuxer {\n  private readonly observer: HlsEventEmitter;\n\n  constructor(observer) {\n    super();\n    this.observer = observer;\n  }\n\n  resetInitSegment(\n    initSegment: Uint8Array | undefined,\n    audioCodec: string | undefined,\n    videoCodec: string | undefined,\n    trackDuration: number,\n  ) {\n    super.resetInitSegment(initSegment, audioCodec, videoCodec, trackDuration);\n    this._audioTrack = {\n      container: 'audio/ac-3',\n      type: 'audio',\n      id: 2,\n      pid: -1,\n      sequenceNumber: 0,\n      segmentCodec: 'ac3',\n      samples: [],\n      manifestCodec: audioCodec,\n      duration: trackDuration,\n      inputTimeScale: 90000,\n      dropped: 0,\n    };\n  }\n\n  canParse(data: Uint8Array, offset: number): boolean {\n    return offset + 64 < data.length;\n  }\n\n  appendFrame(\n    track: DemuxedAudioTrack,\n    data: Uint8Array,\n    offset: number,\n  ): AudioFrame | void {\n    const frameLength = appendFrame(\n      track,\n      data,\n      offset,\n      this.basePTS as number,\n      this.frameIndex,\n    );\n    if (frameLength !== -1) {\n      const sample = track.samples[track.samples.length - 1];\n      return { sample, length: frameLength, missing: 0 };\n    }\n  }\n\n  static probe(data: Uint8Array | undefined): boolean {\n    if (!data) {\n      return false;\n    }\n\n    const id3Data = getID3Data(data, 0);\n    if (!id3Data) {\n      return false;\n    }\n\n    // look for the ac-3 sync bytes\n    const offset = id3Data.length;\n    if (\n      data[offset] === 0x0b &&\n      data[offset + 1] === 0x77 &&\n      getTimeStamp(id3Data) !== undefined &&\n      // check the bsid to confirm ac-3\n      getAudioBSID(data, offset) < 16\n    ) {\n      return true;\n    }\n    return false;\n  }\n}\n\nexport function appendFrame(\n  track: DemuxedAudioTrack,\n  data: Uint8Array,\n  start: number,\n  pts: number,\n  frameIndex: number,\n): number {\n  if (start + 8 > data.length) {\n    return -1; // not enough bytes left\n  }\n\n  if (data[start] !== 0x0b || data[start + 1] !== 0x77) {\n    return -1; // invalid magic\n  }\n\n  // get sample rate\n  const samplingRateCode = data[start + 4] >> 6;\n  if (samplingRateCode >= 3) {\n    return -1; // invalid sampling rate\n  }\n\n  const samplingRateMap = [48000, 44100, 32000];\n  const sampleRate = samplingRateMap[samplingRateCode];\n\n  // get frame size\n  const frameSizeCode = data[start + 4] & 0x3f;\n  const frameSizeMap = [\n    64, 69, 96, 64, 70, 96, 80, 87, 120, 80, 88, 120, 96, 104, 144, 96, 105,\n    144, 112, 121, 168, 112, 122, 168, 128, 139, 192, 128, 140, 192, 160, 174,\n    240, 160, 175, 240, 192, 208, 288, 192, 209, 288, 224, 243, 336, 224, 244,\n    336, 256, 278, 384, 256, 279, 384, 320, 348, 480, 320, 349, 480, 384, 417,\n    576, 384, 418, 576, 448, 487, 672, 448, 488, 672, 512, 557, 768, 512, 558,\n    768, 640, 696, 960, 640, 697, 960, 768, 835, 1152, 768, 836, 1152, 896, 975,\n    1344, 896, 976, 1344, 1024, 1114, 1536, 1024, 1115, 1536, 1152, 1253, 1728,\n    1152, 1254, 1728, 1280, 1393, 1920, 1280, 1394, 1920,\n  ];\n\n  const frameLength = frameSizeMap[frameSizeCode * 3 + samplingRateCode] * 2;\n  if (start + frameLength > data.length) {\n    return -1;\n  }\n\n  // get channel count\n  const channelMode = data[start + 6] >> 5;\n  let skipCount = 0;\n  if (channelMode === 2) {\n    skipCount += 2;\n  } else {\n    if (channelMode & 1 && channelMode !== 1) {\n      skipCount += 2;\n    }\n    if (channelMode & 4) {\n      skipCount += 2;\n    }\n  }\n\n  const lfeon =\n    (((data[start + 6] << 8) | data[start + 7]) >> (12 - skipCount)) & 1;\n\n  const channelsMap = [2, 1, 2, 3, 3, 4, 4, 5];\n  const channelCount = channelsMap[channelMode] + lfeon;\n\n  // build dac3 box\n  const bsid = data[start + 5] >> 3;\n  const bsmod = data[start + 5] & 7;\n\n  const config = new Uint8Array([\n    (samplingRateCode << 6) | (bsid << 1) | (bsmod >> 2),\n    ((bsmod & 3) << 6) |\n      (channelMode << 3) |\n      (lfeon << 2) |\n      (frameSizeCode >> 4),\n    (frameSizeCode << 4) & 0xe0,\n  ]);\n\n  const frameDuration = (1536 / sampleRate) * 90000;\n  const stamp = pts + frameIndex * frameDuration;\n  const unit = data.subarray(start, start + frameLength);\n\n  track.config = config;\n  track.channelCount = channelCount;\n  track.samplerate = sampleRate;\n  track.samples.push({ unit, pts: stamp });\n\n  return frameLength;\n}\n", "import type { ParsedVideoSample } from '../tsdemuxer';\nimport {\n  DemuxedVideoTrack,\n  VideoSample,\n  VideoSampleUnit,\n} from '../../types/demuxer';\nimport { logger } from '../../utils/logger';\n\nclass BaseVideoParser {\n  protected VideoSample: ParsedVideoSample | null = null;\n\n  protected createVideoSample(\n    key: boolean,\n    pts: number | undefined,\n    dts: number | undefined,\n    debug: string,\n  ): ParsedVideoSample {\n    return {\n      key,\n      frame: false,\n      pts,\n      dts,\n      units: [],\n      debug,\n      length: 0,\n    };\n  }\n\n  protected getLastNalUnit(\n    samples: VideoSample[],\n  ): VideoSampleUnit | undefined {\n    let VideoSample = this.VideoSample;\n    let lastUnit: VideoSampleUnit | undefined;\n    // try to fallback to previous sample if current one is empty\n    if (!VideoSample || VideoSample.units.length === 0) {\n      VideoSample = samples[samples.length - 1];\n    }\n    if (VideoSample?.units) {\n      const units = VideoSample.units;\n      lastUnit = units[units.length - 1];\n    }\n    return lastUnit;\n  }\n\n  protected pushAccessUnit(\n    VideoSample: ParsedVideoSample,\n    videoTrack: DemuxedVideoTrack,\n  ) {\n    if (VideoSample.units.length && VideoSample.frame) {\n      // if sample does not have PTS/DTS, patch with last sample PTS/DTS\n      if (VideoSample.pts === undefined) {\n        const samples = videoTrack.samples;\n        const nbSamples = samples.length;\n        if (nbSamples) {\n          const lastSample = samples[nbSamples - 1];\n          VideoSample.pts = lastSample.pts;\n          VideoSample.dts = lastSample.dts;\n        } else {\n          // dropping samples, no timestamp found\n          videoTrack.dropped++;\n          return;\n        }\n      }\n      videoTrack.samples.push(VideoSample as VideoSample);\n    }\n    if (VideoSample.debug.length) {\n      logger.log(\n        VideoSample.pts + '/' + VideoSample.dts + ':' + VideoSample.debug,\n      );\n    }\n  }\n}\n\nexport default BaseVideoParser;\n", "/**\n * Parser for exponential Golomb codes, a variable-bitwidth number encoding scheme used by h264.\n */\n\nimport { logger } from '../../utils/logger';\n\nclass ExpGolomb {\n  private data: Uint8Array;\n  public bytesAvailable: number;\n  private word: number;\n  private bitsAvailable: number;\n\n  constructor(data: Uint8Array) {\n    this.data = data;\n    // the number of bytes left to examine in this.data\n    this.bytesAvailable = data.byteLength;\n    // the current word being examined\n    this.word = 0; // :uint\n    // the number of bits left to examine in the current word\n    this.bitsAvailable = 0; // :uint\n  }\n\n  // ():void\n  loadWord(): void {\n    const data = this.data;\n    const bytesAvailable = this.bytesAvailable;\n    const position = data.byteLength - bytesAvailable;\n    const workingBytes = new Uint8Array(4);\n    const availableBytes = Math.min(4, bytesAvailable);\n    if (availableBytes === 0) {\n      throw new Error('no bytes available');\n    }\n\n    workingBytes.set(data.subarray(position, position + availableBytes));\n    this.word = new DataView(workingBytes.buffer).getUint32(0);\n    // track the amount of this.data that has been processed\n    this.bitsAvailable = availableBytes * 8;\n    this.bytesAvailable -= availableBytes;\n  }\n\n  // (count:int):void\n  skipBits(count: number): void {\n    let skipBytes; // :int\n    count = Math.min(count, this.bytesAvailable * 8 + this.bitsAvailable);\n    if (this.bitsAvailable > count) {\n      this.word <<= count;\n      this.bitsAvailable -= count;\n    } else {\n      count -= this.bitsAvailable;\n      skipBytes = count >> 3;\n      count -= skipBytes << 3;\n      this.bytesAvailable -= skipBytes;\n      this.loadWord();\n      this.word <<= count;\n      this.bitsAvailable -= count;\n    }\n  }\n\n  // (size:int):uint\n  readBits(size: number): number {\n    let bits = Math.min(this.bitsAvailable, size); // :uint\n    const valu = this.word >>> (32 - bits); // :uint\n    if (size > 32) {\n      logger.error('Cannot read more than 32 bits at a time');\n    }\n\n    this.bitsAvailable -= bits;\n    if (this.bitsAvailable > 0) {\n      this.word <<= bits;\n    } else if (this.bytesAvailable > 0) {\n      this.loadWord();\n    } else {\n      throw new Error('no bits available');\n    }\n\n    bits = size - bits;\n    if (bits > 0 && this.bitsAvailable) {\n      return (valu << bits) | this.readBits(bits);\n    } else {\n      return valu;\n    }\n  }\n\n  // ():uint\n  skipLZ(): number {\n    let leadingZeroCount; // :uint\n    for (\n      leadingZeroCount = 0;\n      leadingZeroCount < this.bitsAvailable;\n      ++leadingZeroCount\n    ) {\n      if ((this.word & (0x80000000 >>> leadingZeroCount)) !== 0) {\n        // the first bit of working word is 1\n        this.word <<= leadingZeroCount;\n        this.bitsAvailable -= leadingZeroCount;\n        return leadingZeroCount;\n      }\n    }\n    // we exhausted word and still have not found a 1\n    this.loadWord();\n    return leadingZeroCount + this.skipLZ();\n  }\n\n  // ():void\n  skipUEG(): void {\n    this.skipBits(1 + this.skipLZ());\n  }\n\n  // ():void\n  skipEG(): void {\n    this.skipBits(1 + this.skipLZ());\n  }\n\n  // ():uint\n  readUEG(): number {\n    const clz = this.skipLZ(); // :uint\n    return this.readBits(clz + 1) - 1;\n  }\n\n  // ():int\n  readEG(): number {\n    const valu = this.readUEG(); // :int\n    if (0x01 & valu) {\n      // the number is odd if the low order bit is set\n      return (1 + valu) >>> 1; // add 1 to make it even, and divide by 2\n    } else {\n      return -1 * (valu >>> 1); // divide by two then make it negative\n    }\n  }\n\n  // Some convenience functions\n  // :Boolean\n  readBoolean(): boolean {\n    return this.readBits(1) === 1;\n  }\n\n  // ():int\n  readUByte(): number {\n    return this.readBits(8);\n  }\n\n  // ():int\n  readUShort(): number {\n    return this.readBits(16);\n  }\n\n  // ():int\n  readUInt(): number {\n    return this.readBits(32);\n  }\n\n  /**\n   * Advance the ExpGolomb decoder past a scaling list. The scaling\n   * list is optionally transmitted as part of a sequence parameter\n   * set and is not relevant to transmuxing.\n   * @param count the number of entries in this scaling list\n   * @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1\n   */\n  skipScalingList(count: number): void {\n    let lastScale = 8;\n    let nextScale = 8;\n    let deltaScale;\n    for (let j = 0; j < count; j++) {\n      if (nextScale !== 0) {\n        deltaScale = this.readEG();\n        nextScale = (lastScale + deltaScale + 256) % 256;\n      }\n      lastScale = nextScale === 0 ? lastScale : nextScale;\n    }\n  }\n\n  /**\n   * Read a sequence parameter set and return some interesting video\n   * properties. A sequence parameter set is the H264 metadata that\n   * describes the properties of upcoming video frames.\n   * @returns an object with configuration parsed from the\n   * sequence parameter set, including the dimensions of the\n   * associated video frames.\n   */\n  readSPS(): {\n    width: number;\n    height: number;\n    pixelRatio: [number, number];\n  } {\n    let frameCropLeftOffset = 0;\n    let frameCropRightOffset = 0;\n    let frameCropTopOffset = 0;\n    let frameCropBottomOffset = 0;\n    let numRefFramesInPicOrderCntCycle;\n    let scalingListCount;\n    let i;\n    const readUByte = this.readUByte.bind(this);\n    const readBits = this.readBits.bind(this);\n    const readUEG = this.readUEG.bind(this);\n    const readBoolean = this.readBoolean.bind(this);\n    const skipBits = this.skipBits.bind(this);\n    const skipEG = this.skipEG.bind(this);\n    const skipUEG = this.skipUEG.bind(this);\n    const skipScalingList = this.skipScalingList.bind(this);\n\n    readUByte();\n    const profileIdc = readUByte(); // profile_idc\n    readBits(5); // profileCompat constraint_set[0-4]_flag, u(5)\n    skipBits(3); // reserved_zero_3bits u(3),\n    readUByte(); // level_idc u(8)\n    skipUEG(); // seq_parameter_set_id\n    // some profiles have more optional data we don't need\n    if (\n      profileIdc === 100 ||\n      profileIdc === 110 ||\n      profileIdc === 122 ||\n      profileIdc === 244 ||\n      profileIdc === 44 ||\n      profileIdc === 83 ||\n      profileIdc === 86 ||\n      profileIdc === 118 ||\n      profileIdc === 128\n    ) {\n      const chromaFormatIdc = readUEG();\n      if (chromaFormatIdc === 3) {\n        skipBits(1);\n      } // separate_colour_plane_flag\n\n      skipUEG(); // bit_depth_luma_minus8\n      skipUEG(); // bit_depth_chroma_minus8\n      skipBits(1); // qpprime_y_zero_transform_bypass_flag\n      if (readBoolean()) {\n        // seq_scaling_matrix_present_flag\n        scalingListCount = chromaFormatIdc !== 3 ? 8 : 12;\n        for (i = 0; i < scalingListCount; i++) {\n          if (readBoolean()) {\n            // seq_scaling_list_present_flag[ i ]\n            if (i < 6) {\n              skipScalingList(16);\n            } else {\n              skipScalingList(64);\n            }\n          }\n        }\n      }\n    }\n    skipUEG(); // log2_max_frame_num_minus4\n    const picOrderCntType = readUEG();\n    if (picOrderCntType === 0) {\n      readUEG(); // log2_max_pic_order_cnt_lsb_minus4\n    } else if (picOrderCntType === 1) {\n      skipBits(1); // delta_pic_order_always_zero_flag\n      skipEG(); // offset_for_non_ref_pic\n      skipEG(); // offset_for_top_to_bottom_field\n      numRefFramesInPicOrderCntCycle = readUEG();\n      for (i = 0; i < numRefFramesInPicOrderCntCycle; i++) {\n        skipEG();\n      } // offset_for_ref_frame[ i ]\n    }\n    skipUEG(); // max_num_ref_frames\n    skipBits(1); // gaps_in_frame_num_value_allowed_flag\n    const picWidthInMbsMinus1 = readUEG();\n    const picHeightInMapUnitsMinus1 = readUEG();\n    const frameMbsOnlyFlag = readBits(1);\n    if (frameMbsOnlyFlag === 0) {\n      skipBits(1);\n    } // mb_adaptive_frame_field_flag\n\n    skipBits(1); // direct_8x8_inference_flag\n    if (readBoolean()) {\n      // frame_cropping_flag\n      frameCropLeftOffset = readUEG();\n      frameCropRightOffset = readUEG();\n      frameCropTopOffset = readUEG();\n      frameCropBottomOffset = readUEG();\n    }\n    let pixelRatio: [number, number] = [1, 1];\n    if (readBoolean()) {\n      // vui_parameters_present_flag\n      if (readBoolean()) {\n        // aspect_ratio_info_present_flag\n        const aspectRatioIdc = readUByte();\n        switch (aspectRatioIdc) {\n          case 1:\n            pixelRatio = [1, 1];\n            break;\n          case 2:\n            pixelRatio = [12, 11];\n            break;\n          case 3:\n            pixelRatio = [10, 11];\n            break;\n          case 4:\n            pixelRatio = [16, 11];\n            break;\n          case 5:\n            pixelRatio = [40, 33];\n            break;\n          case 6:\n            pixelRatio = [24, 11];\n            break;\n          case 7:\n            pixelRatio = [20, 11];\n            break;\n          case 8:\n            pixelRatio = [32, 11];\n            break;\n          case 9:\n            pixelRatio = [80, 33];\n            break;\n          case 10:\n            pixelRatio = [18, 11];\n            break;\n          case 11:\n            pixelRatio = [15, 11];\n            break;\n          case 12:\n            pixelRatio = [64, 33];\n            break;\n          case 13:\n            pixelRatio = [160, 99];\n            break;\n          case 14:\n            pixelRatio = [4, 3];\n            break;\n          case 15:\n            pixelRatio = [3, 2];\n            break;\n          case 16:\n            pixelRatio = [2, 1];\n            break;\n          case 255: {\n            pixelRatio = [\n              (readUByte() << 8) | readUByte(),\n              (readUByte() << 8) | readUByte(),\n            ];\n            break;\n          }\n        }\n      }\n    }\n    return {\n      width: Math.ceil(\n        (picWidthInMbsMinus1 + 1) * 16 -\n          frameCropLeftOffset * 2 -\n          frameCropRightOffset * 2,\n      ),\n      height:\n        (2 - frameMbsOnlyFlag) * (picHeightInMapUnitsMinus1 + 1) * 16 -\n        (frameMbsOnlyFlag ? 2 : 4) *\n          (frameCropTopOffset + frameCropBottomOffset),\n      pixelRatio: pixelRatio,\n    };\n  }\n\n  readSliceType() {\n    // skip NALu type\n    this.readUByte();\n    // discard first_mb_in_slice\n    this.readUEG();\n    // return slice_type\n    return this.readUEG();\n  }\n}\n\nexport default ExpGolomb;\n", "import BaseVideoParser from './base-video-parser';\nimport {\n  DemuxedVideoTrack,\n  DemuxedUserdataTrack,\n  VideoSampleUnit,\n} from '../../types/demuxer';\nimport {\n  appendUint8Array,\n  parseSEIMessageFromNALu,\n} from '../../utils/mp4-tools';\nimport ExpGolomb from './exp-golomb';\nimport type { PES } from '../tsdemuxer';\n\nclass AvcVideoParser extends BaseVideoParser {\n  public parseAVCPES(\n    track: DemuxedVideoTrack,\n    textTrack: DemuxedUserdataTrack,\n    pes: PES,\n    last: boolean,\n    duration: number,\n  ) {\n    const units = this.parseAVCNALu(track, pes.data);\n    const debug = false;\n    let VideoSample = this.VideoSample;\n    let push: boolean;\n    let spsfound = false;\n    // free pes.data to save up some memory\n    (pes as any).data = null;\n\n    // if new NAL units found and last sample still there, let's push ...\n    // this helps parsing streams with missing AUD (only do this if AUD never found)\n    if (VideoSample && units.length && !track.audFound) {\n      this.pushAccessUnit(VideoSample, track);\n      VideoSample = this.VideoSample = this.createVideoSample(\n        false,\n        pes.pts,\n        pes.dts,\n        '',\n      );\n    }\n\n    units.forEach((unit) => {\n      switch (unit.type) {\n        // NDR\n        case 1: {\n          let iskey = false;\n          push = true;\n          const data = unit.data;\n          // only check slice type to detect KF in case SPS found in same packet (any keyframe is preceded by SPS ...)\n          if (spsfound && data.length > 4) {\n            // retrieve slice type by parsing beginning of NAL unit (follow H264 spec, slice_header definition) to detect keyframe embedded in NDR\n            const sliceType = new ExpGolomb(data).readSliceType();\n            // 2 : I slice, 4 : SI slice, 7 : I slice, 9: SI slice\n            // SI slice : A slice that is coded using intra prediction only and using quantisation of the prediction samples.\n            // An SI slice can be coded such that its decoded samples can be constructed identically to an SP slice.\n            // I slice: A slice that is not an SI slice that is decoded using intra prediction only.\n            // if (sliceType === 2 || sliceType === 7) {\n            if (\n              sliceType === 2 ||\n              sliceType === 4 ||\n              sliceType === 7 ||\n              sliceType === 9\n            ) {\n              iskey = true;\n            }\n          }\n\n          if (iskey) {\n            // if we have non-keyframe data already, that cannot belong to the same frame as a keyframe, so force a push\n            if (VideoSample?.frame && !VideoSample.key) {\n              this.pushAccessUnit(VideoSample, track);\n              VideoSample = this.VideoSample = null;\n            }\n          }\n\n          if (!VideoSample) {\n            VideoSample = this.VideoSample = this.createVideoSample(\n              true,\n              pes.pts,\n              pes.dts,\n              '',\n            );\n          }\n\n          if (debug) {\n            VideoSample.debug += 'NDR ';\n          }\n\n          VideoSample.frame = true;\n          VideoSample.key = iskey;\n\n          break;\n          // IDR\n        }\n        case 5:\n          push = true;\n          // handle PES not starting with AUD\n          // if we have frame data already, that cannot belong to the same frame, so force a push\n          if (VideoSample?.frame && !VideoSample.key) {\n            this.pushAccessUnit(VideoSample, track);\n            VideoSample = this.VideoSample = null;\n          }\n          if (!VideoSample) {\n            VideoSample = this.VideoSample = this.createVideoSample(\n              true,\n              pes.pts,\n              pes.dts,\n              '',\n            );\n          }\n\n          if (debug) {\n            VideoSample.debug += 'IDR ';\n          }\n\n          VideoSample.key = true;\n          VideoSample.frame = true;\n          break;\n        // SEI\n        case 6: {\n          push = true;\n          if (debug && VideoSample) {\n            VideoSample.debug += 'SEI ';\n          }\n          parseSEIMessageFromNALu(\n            unit.data,\n            1,\n            pes.pts as number,\n            textTrack.samples,\n          );\n          break;\n          // SPS\n        }\n        case 7: {\n          push = true;\n          spsfound = true;\n          if (debug && VideoSample) {\n            VideoSample.debug += 'SPS ';\n          }\n          const sps = unit.data;\n          const expGolombDecoder = new ExpGolomb(sps);\n          const config = expGolombDecoder.readSPS();\n\n          if (\n            !track.sps ||\n            track.width !== config.width ||\n            track.height !== config.height ||\n            track.pixelRatio?.[0] !== config.pixelRatio[0] ||\n            track.pixelRatio?.[1] !== config.pixelRatio[1]\n          ) {\n            track.width = config.width;\n            track.height = config.height;\n            track.pixelRatio = config.pixelRatio;\n            track.sps = [sps];\n            track.duration = duration;\n            const codecarray = sps.subarray(1, 4);\n            let codecstring = 'avc1.';\n            for (let i = 0; i < 3; i++) {\n              let h = codecarray[i].toString(16);\n              if (h.length < 2) {\n                h = '0' + h;\n              }\n\n              codecstring += h;\n            }\n            track.codec = codecstring;\n          }\n\n          break;\n        }\n        // PPS\n        case 8:\n          push = true;\n          if (debug && VideoSample) {\n            VideoSample.debug += 'PPS ';\n          }\n\n          track.pps = [unit.data];\n\n          break;\n        // AUD\n        case 9:\n          push = true;\n          track.audFound = true;\n          if (VideoSample) {\n            this.pushAccessUnit(VideoSample, track);\n          }\n\n          VideoSample = this.VideoSample = this.createVideoSample(\n            false,\n            pes.pts,\n            pes.dts,\n            debug ? 'AUD ' : '',\n          );\n          break;\n        // Filler Data\n        case 12:\n          push = true;\n          break;\n        default:\n          push = false;\n          if (VideoSample) {\n            VideoSample.debug += 'unknown NAL ' + unit.type + ' ';\n          }\n\n          break;\n      }\n      if (VideoSample && push) {\n        const units = VideoSample.units;\n        units.push(unit);\n      }\n    });\n    // if last PES packet, push samples\n    if (last && VideoSample) {\n      this.pushAccessUnit(VideoSample, track);\n      this.VideoSample = null;\n    }\n  }\n\n  private parseAVCNALu(\n    track: DemuxedVideoTrack,\n    array: Uint8Array,\n  ): Array<{\n    data: Uint8Array;\n    type: number;\n    state?: number;\n  }> {\n    const len = array.byteLength;\n    let state = track.naluState || 0;\n    const lastState = state;\n    const units: VideoSampleUnit[] = [];\n    let i = 0;\n    let value: number;\n    let overflow: number;\n    let unitType: number;\n    let lastUnitStart = -1;\n    let lastUnitType: number = 0;\n    // logger.log('PES:' + Hex.hexDump(array));\n\n    if (state === -1) {\n      // special use case where we found 3 or 4-byte start codes exactly at the end of previous PES packet\n      lastUnitStart = 0;\n      // NALu type is value read from offset 0\n      lastUnitType = array[0] & 0x1f;\n      state = 0;\n      i = 1;\n    }\n\n    while (i < len) {\n      value = array[i++];\n      // optimization. state 0 and 1 are the predominant case. let's handle them outside of the switch/case\n      if (!state) {\n        state = value ? 0 : 1;\n        continue;\n      }\n      if (state === 1) {\n        state = value ? 0 : 2;\n        continue;\n      }\n      // here we have state either equal to 2 or 3\n      if (!value) {\n        state = 3;\n      } else if (value === 1) {\n        overflow = i - state - 1;\n        if (lastUnitStart >= 0) {\n          const unit: VideoSampleUnit = {\n            data: array.subarray(lastUnitStart, overflow),\n            type: lastUnitType,\n          };\n          // logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength);\n          units.push(unit);\n        } else {\n          // lastUnitStart is undefined => this is the first start code found in this PES packet\n          // first check if start code delimiter is overlapping between 2 PES packets,\n          // ie it started in last packet (lastState not zero)\n          // and ended at the beginning of this PES packet (i <= 4 - lastState)\n          const lastUnit = this.getLastNalUnit(track.samples);\n          if (lastUnit) {\n            if (lastState && i <= 4 - lastState) {\n              // start delimiter overlapping between PES packets\n              // strip start delimiter bytes from the end of last NAL unit\n              // check if lastUnit had a state different from zero\n              if (lastUnit.state) {\n                // strip last bytes\n                lastUnit.data = lastUnit.data.subarray(\n                  0,\n                  lastUnit.data.byteLength - lastState,\n                );\n              }\n            }\n            // If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit.\n\n            if (overflow > 0) {\n              // logger.log('first NALU found with overflow:' + overflow);\n              lastUnit.data = appendUint8Array(\n                lastUnit.data,\n                array.subarray(0, overflow),\n              );\n              lastUnit.state = 0;\n            }\n          }\n        }\n        // check if we can read unit type\n        if (i < len) {\n          unitType = array[i] & 0x1f;\n          // logger.log('find NALU @ offset:' + i + ',type:' + unitType);\n          lastUnitStart = i;\n          lastUnitType = unitType;\n          state = 0;\n        } else {\n          // not enough byte to read unit type. let's read it on next PES parsing\n          state = -1;\n        }\n      } else {\n        state = 0;\n      }\n    }\n    if (lastUnitStart >= 0 && state >= 0) {\n      const unit: VideoSampleUnit = {\n        data: array.subarray(lastUnitStart, len),\n        type: lastUnitType,\n        state: state,\n      };\n      units.push(unit);\n      // logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state);\n    }\n    // no NALu found\n    if (units.length === 0) {\n      // append pes.data to previous NAL unit\n      const lastUnit = this.getLastNalUnit(track.samples);\n      if (lastUnit) {\n        lastUnit.data = appendUint8Array(lastUnit.data, array);\n      }\n    }\n    track.naluState = state;\n    return units;\n  }\n}\n\nexport default AvcVideoParser;\n", "/**\n * SAMPLE-AES decrypter\n */\n\nimport { HlsConfig } from '../config';\nimport Decrypter from '../crypt/decrypter';\nimport { HlsEventEmitter } from '../events';\nimport type {\n  AudioSample,\n  VideoSample,\n  VideoSampleUnit,\n  DemuxedVideoTrackBase,\n  KeyData,\n} from '../types/demuxer';\nimport { discardEPB } from '../utils/mp4-tools';\n\nclass SampleAesDecrypter {\n  private keyData: KeyData;\n  private decrypter: Decrypter;\n\n  constructor(observer: HlsEventEmitter, config: HlsConfig, keyData: KeyData) {\n    this.keyData = keyData;\n    this.decrypter = new Decrypter(config, {\n      removePKCS7Padding: false,\n    });\n  }\n\n  decryptBuffer(encryptedData: Uint8Array | ArrayBuffer): Promise<ArrayBuffer> {\n    return this.decrypter.decrypt(\n      encryptedData,\n      this.keyData.key.buffer,\n      this.keyData.iv.buffer,\n    );\n  }\n\n  // AAC - encrypt all full 16 bytes blocks starting from offset 16\n  private decryptAacSample(\n    samples: AudioSample[],\n    sampleIndex: number,\n    callback: () => void,\n  ) {\n    const curUnit = samples[sampleIndex].unit;\n    if (curUnit.length <= 16) {\n      // No encrypted portion in this sample (first 16 bytes is not\n      // encrypted, see https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/HLS_Sample_Encryption/Encryption/Encryption.html),\n      return;\n    }\n    const encryptedData = curUnit.subarray(\n      16,\n      curUnit.length - (curUnit.length % 16),\n    );\n    const encryptedBuffer = encryptedData.buffer.slice(\n      encryptedData.byteOffset,\n      encryptedData.byteOffset + encryptedData.length,\n    );\n\n    this.decryptBuffer(encryptedBuffer).then((decryptedBuffer: ArrayBuffer) => {\n      const decryptedData = new Uint8Array(decryptedBuffer);\n      curUnit.set(decryptedData, 16);\n\n      if (!this.decrypter.isSync()) {\n        this.decryptAacSamples(samples, sampleIndex + 1, callback);\n      }\n    });\n  }\n\n  decryptAacSamples(\n    samples: AudioSample[],\n    sampleIndex: number,\n    callback: () => void,\n  ) {\n    for (; ; sampleIndex++) {\n      if (sampleIndex >= samples.length) {\n        callback();\n        return;\n      }\n\n      if (samples[sampleIndex].unit.length < 32) {\n        continue;\n      }\n\n      this.decryptAacSample(samples, sampleIndex, callback);\n\n      if (!this.decrypter.isSync()) {\n        return;\n      }\n    }\n  }\n\n  // AVC - encrypt one 16 bytes block out of ten, starting from offset 32\n  getAvcEncryptedData(decodedData: Uint8Array) {\n    const encryptedDataLen =\n      Math.floor((decodedData.length - 48) / 160) * 16 + 16;\n    const encryptedData = new Int8Array(encryptedDataLen);\n    let outputPos = 0;\n    for (\n      let inputPos = 32;\n      inputPos < decodedData.length - 16;\n      inputPos += 160, outputPos += 16\n    ) {\n      encryptedData.set(\n        decodedData.subarray(inputPos, inputPos + 16),\n        outputPos,\n      );\n    }\n\n    return encryptedData;\n  }\n\n  getAvcDecryptedUnit(\n    decodedData: Uint8Array,\n    decryptedData: ArrayLike<number> | ArrayBuffer | SharedArrayBuffer,\n  ) {\n    const uint8DecryptedData = new Uint8Array(decryptedData);\n    let inputPos = 0;\n    for (\n      let outputPos = 32;\n      outputPos < decodedData.length - 16;\n      outputPos += 160, inputPos += 16\n    ) {\n      decodedData.set(\n        uint8DecryptedData.subarray(inputPos, inputPos + 16),\n        outputPos,\n      );\n    }\n\n    return decodedData;\n  }\n\n  decryptAvcSample(\n    samples: VideoSample[],\n    sampleIndex: number,\n    unitIndex: number,\n    callback: () => void,\n    curUnit: VideoSampleUnit,\n  ) {\n    const decodedData = discardEPB(curUnit.data);\n    const encryptedData = this.getAvcEncryptedData(decodedData);\n\n    this.decryptBuffer(encryptedData.buffer).then(\n      (decryptedBuffer: ArrayBuffer) => {\n        curUnit.data = this.getAvcDecryptedUnit(decodedData, decryptedBuffer);\n\n        if (!this.decrypter.isSync()) {\n          this.decryptAvcSamples(samples, sampleIndex, unitIndex + 1, callback);\n        }\n      },\n    );\n  }\n\n  decryptAvcSamples(\n    samples: DemuxedVideoTrackBase['samples'],\n    sampleIndex: number,\n    unitIndex: number,\n    callback: () => void,\n  ) {\n    if (samples instanceof Uint8Array) {\n      throw new Error('Cannot decrypt samples of type Uint8Array');\n    }\n\n    for (; ; sampleIndex++, unitIndex = 0) {\n      if (sampleIndex >= samples.length) {\n        callback();\n        return;\n      }\n\n      const curUnits = samples[sampleIndex].units;\n      for (; ; unitIndex++) {\n        if (unitIndex >= curUnits.length) {\n          break;\n        }\n\n        const curUnit = curUnits[unitIndex];\n        if (\n          curUnit.data.length <= 48 ||\n          (curUnit.type !== 1 && curUnit.type !== 5)\n        ) {\n          continue;\n        }\n\n        this.decryptAvcSample(\n          samples,\n          sampleIndex,\n          unitIndex,\n          callback,\n          curUnit,\n        );\n\n        if (!this.decrypter.isSync()) {\n          return;\n        }\n      }\n    }\n  }\n}\n\nexport default SampleAesDecrypter;\n", "/**\n * highly optimized TS demuxer:\n * parse PAT, PMT\n * extract PES packet from audio and video PIDs\n * extract AVC/H264 NAL units and AAC/ADTS samples from PES packet\n * trigger the remuxer upon parsing completion\n * it also tries to workaround as best as it can audio codec switch (HE-AAC to AAC and vice versa), without having to restart the MediaSource.\n * it also controls the remuxing process :\n * upon discontinuity or level switch detection, it will also notifies the remuxer so that it can reset its state.\n */\n\nimport * as ADTS from './audio/adts';\nimport * as MpegAudio from './audio/mpegaudio';\nimport * as AC3 from './audio/ac3-demuxer';\nimport AvcVideoParser from './video/avc-video-parser';\nimport SampleAesDecrypter from './sample-aes';\nimport { Events } from '../events';\nimport { appendUint8Array, RemuxerTrackIdConfig } from '../utils/mp4-tools';\nimport { logger } from '../utils/logger';\nimport { ErrorTypes, ErrorDetails } from '../errors';\nimport type { HlsConfig } from '../config';\nimport type { HlsEventEmitter } from '../events';\nimport {\n  DemuxedVideoTrack,\n  DemuxedAudioTrack,\n  DemuxedTrack,\n  Demuxer,\n  DemuxerResult,\n  VideoSample,\n  DemuxedMetadataTrack,\n  DemuxedUserdataTrack,\n  ElementaryStreamData,\n  KeyData,\n  MetadataSchema,\n} from '../types/demuxer';\nimport { AudioFrame } from '../types/demuxer';\n\nexport type ParsedTimestamp = {\n  pts?: number;\n  dts?: number;\n};\n\nexport type PES = ParsedTimestamp & {\n  data: Uint8Array;\n  len: number;\n};\n\nexport type ParsedVideoSample = ParsedTimestamp &\n  Omit<VideoSample, 'pts' | 'dts'>;\n\nexport interface TypeSupported {\n  mpeg: boolean;\n  mp3: boolean;\n  ac3: boolean;\n}\n\nconst PACKET_LENGTH = 188;\n\nclass TSDemuxer implements Demuxer {\n  private readonly observer: HlsEventEmitter;\n  private readonly config: HlsConfig;\n  private typeSupported: TypeSupported;\n\n  private sampleAes: SampleAesDecrypter | null = null;\n  private pmtParsed: boolean = false;\n  private audioCodec?: string;\n  private videoCodec?: string;\n  private _duration: number = 0;\n  private _pmtId: number = -1;\n\n  private _videoTrack?: DemuxedVideoTrack;\n  private _audioTrack?: DemuxedAudioTrack;\n  private _id3Track?: DemuxedMetadataTrack;\n  private _txtTrack?: DemuxedUserdataTrack;\n  private aacOverFlow: AudioFrame | null = null;\n  private remainderData: Uint8Array | null = null;\n  private videoParser: AvcVideoParser;\n\n  constructor(\n    observer: HlsEventEmitter,\n    config: HlsConfig,\n    typeSupported: TypeSupported,\n  ) {\n    this.observer = observer;\n    this.config = config;\n    this.typeSupported = typeSupported;\n    this.videoParser = new AvcVideoParser();\n  }\n\n  static probe(data: Uint8Array) {\n    const syncOffset = TSDemuxer.syncOffset(data);\n    if (syncOffset > 0) {\n      logger.warn(\n        `MPEG2-TS detected but first sync word found @ offset ${syncOffset}`,\n      );\n    }\n    return syncOffset !== -1;\n  }\n\n  static syncOffset(data: Uint8Array): number {\n    const length = data.length;\n    let scanwindow = Math.min(PACKET_LENGTH * 5, length - PACKET_LENGTH) + 1;\n    let i = 0;\n    while (i < scanwindow) {\n      // a TS init segment should contain at least 2 TS packets: PAT and PMT, each starting with 0x47\n      let foundPat = false;\n      let packetStart = -1;\n      let tsPackets = 0;\n      for (let j = i; j < length; j += PACKET_LENGTH) {\n        if (\n          data[j] === 0x47 &&\n          (length - j === PACKET_LENGTH || data[j + PACKET_LENGTH] === 0x47)\n        ) {\n          tsPackets++;\n          if (packetStart === -1) {\n            packetStart = j;\n            // First sync word found at offset, increase scan length (#5251)\n            if (packetStart !== 0) {\n              scanwindow =\n                Math.min(\n                  packetStart + PACKET_LENGTH * 99,\n                  data.length - PACKET_LENGTH,\n                ) + 1;\n            }\n          }\n          if (!foundPat) {\n            foundPat = parsePID(data, j) === 0;\n          }\n          // Sync word found at 0 with 3 packets, or found at offset least 2 packets up to scanwindow (#5501)\n          if (\n            foundPat &&\n            tsPackets > 1 &&\n            ((packetStart === 0 && tsPackets > 2) ||\n              j + PACKET_LENGTH > scanwindow)\n          ) {\n            return packetStart;\n          }\n        } else if (tsPackets) {\n          // Exit if sync word found, but does not contain contiguous packets\n          return -1;\n        } else {\n          break;\n        }\n      }\n      i++;\n    }\n    return -1;\n  }\n\n  /**\n   * Creates a track model internal to demuxer used to drive remuxing input\n   */\n  static createTrack(\n    type: 'audio' | 'video' | 'id3' | 'text',\n    duration?: number,\n  ): DemuxedTrack {\n    return {\n      container:\n        type === 'video' || type === 'audio' ? 'video/mp2t' : undefined,\n      type,\n      id: RemuxerTrackIdConfig[type],\n      pid: -1,\n      inputTimeScale: 90000,\n      sequenceNumber: 0,\n      samples: [],\n      dropped: 0,\n      duration: type === 'audio' ? duration : undefined,\n    };\n  }\n\n  /**\n   * Initializes a new init segment on the demuxer/remuxer interface. Needed for discontinuities/track-switches (or at stream start)\n   * Resets all internal track instances of the demuxer.\n   */\n  public resetInitSegment(\n    initSegment: Uint8Array | undefined,\n    audioCodec: string,\n    videoCodec: string,\n    trackDuration: number,\n  ) {\n    this.pmtParsed = false;\n    this._pmtId = -1;\n\n    this._videoTrack = TSDemuxer.createTrack('video') as DemuxedVideoTrack;\n    this._audioTrack = TSDemuxer.createTrack(\n      'audio',\n      trackDuration,\n    ) as DemuxedAudioTrack;\n    this._id3Track = TSDemuxer.createTrack('id3') as DemuxedMetadataTrack;\n    this._txtTrack = TSDemuxer.createTrack('text') as DemuxedUserdataTrack;\n    this._audioTrack.segmentCodec = 'aac';\n\n    // flush any partial content\n    this.aacOverFlow = null;\n    this.remainderData = null;\n    this.audioCodec = audioCodec;\n    this.videoCodec = videoCodec;\n    this._duration = trackDuration;\n  }\n\n  public resetTimeStamp() {}\n\n  public resetContiguity(): void {\n    const { _audioTrack, _videoTrack, _id3Track } = this;\n    if (_audioTrack) {\n      _audioTrack.pesData = null;\n    }\n    if (_videoTrack) {\n      _videoTrack.pesData = null;\n    }\n    if (_id3Track) {\n      _id3Track.pesData = null;\n    }\n    this.aacOverFlow = null;\n    this.remainderData = null;\n  }\n\n  public demux(\n    data: Uint8Array,\n    timeOffset: number,\n    isSampleAes = false,\n    flush = false,\n  ): DemuxerResult {\n    if (!isSampleAes) {\n      this.sampleAes = null;\n    }\n\n    let pes: PES | null;\n\n    const videoTrack = this._videoTrack as DemuxedVideoTrack;\n    const audioTrack = this._audioTrack as DemuxedAudioTrack;\n    const id3Track = this._id3Track as DemuxedMetadataTrack;\n    const textTrack = this._txtTrack as DemuxedUserdataTrack;\n\n    let videoPid = videoTrack.pid;\n    let videoData = videoTrack.pesData;\n    let audioPid = audioTrack.pid;\n    let id3Pid = id3Track.pid;\n    let audioData = audioTrack.pesData;\n    let id3Data = id3Track.pesData;\n    let unknownPID: number | null = null;\n    let pmtParsed = this.pmtParsed;\n    let pmtId = this._pmtId;\n\n    let len = data.length;\n    if (this.remainderData) {\n      data = appendUint8Array(this.remainderData, data);\n      len = data.length;\n      this.remainderData = null;\n    }\n\n    if (len < PACKET_LENGTH && !flush) {\n      this.remainderData = data;\n      return {\n        audioTrack,\n        videoTrack,\n        id3Track,\n        textTrack,\n      };\n    }\n\n    const syncOffset = Math.max(0, TSDemuxer.syncOffset(data));\n    len -= (len - syncOffset) % PACKET_LENGTH;\n    if (len < data.byteLength && !flush) {\n      this.remainderData = new Uint8Array(\n        data.buffer,\n        len,\n        data.buffer.byteLength - len,\n      );\n    }\n\n    // loop through TS packets\n    let tsPacketErrors = 0;\n    for (let start = syncOffset; start < len; start += PACKET_LENGTH) {\n      if (data[start] === 0x47) {\n        const stt = !!(data[start + 1] & 0x40);\n        const pid = parsePID(data, start);\n        const atf = (data[start + 3] & 0x30) >> 4;\n\n        // if an adaption field is present, its length is specified by the fifth byte of the TS packet header.\n        let offset: number;\n        if (atf > 1) {\n          offset = start + 5 + data[start + 4];\n          // continue if there is only adaptation field\n          if (offset === start + PACKET_LENGTH) {\n            continue;\n          }\n        } else {\n          offset = start + 4;\n        }\n        switch (pid) {\n          case videoPid:\n            if (stt) {\n              if (videoData && (pes = parsePES(videoData))) {\n                this.videoParser.parseAVCPES(\n                  videoTrack,\n                  textTrack,\n                  pes,\n                  false,\n                  this._duration,\n                );\n              }\n\n              videoData = { data: [], size: 0 };\n            }\n            if (videoData) {\n              videoData.data.push(data.subarray(offset, start + PACKET_LENGTH));\n              videoData.size += start + PACKET_LENGTH - offset;\n            }\n            break;\n          case audioPid:\n            if (stt) {\n              if (audioData && (pes = parsePES(audioData))) {\n                switch (audioTrack.segmentCodec) {\n                  case 'aac':\n                    this.parseAACPES(audioTrack, pes);\n                    break;\n                  case 'mp3':\n                    this.parseMPEGPES(audioTrack, pes);\n                    break;\n                  case 'ac3':\n                    if (__USE_M2TS_ADVANCED_CODECS__) {\n                      this.parseAC3PES(audioTrack, pes);\n                    }\n                    break;\n                }\n              }\n              audioData = { data: [], size: 0 };\n            }\n            if (audioData) {\n              audioData.data.push(data.subarray(offset, start + PACKET_LENGTH));\n              audioData.size += start + PACKET_LENGTH - offset;\n            }\n            break;\n          case id3Pid:\n            if (stt) {\n              if (id3Data && (pes = parsePES(id3Data))) {\n                this.parseID3PES(id3Track, pes);\n              }\n\n              id3Data = { data: [], size: 0 };\n            }\n            if (id3Data) {\n              id3Data.data.push(data.subarray(offset, start + PACKET_LENGTH));\n              id3Data.size += start + PACKET_LENGTH - offset;\n            }\n            break;\n          case 0:\n            if (stt) {\n              offset += data[offset] + 1;\n            }\n\n            pmtId = this._pmtId = parsePAT(data, offset);\n            // logger.log('PMT PID:'  + this._pmtId);\n            break;\n          case pmtId: {\n            if (stt) {\n              offset += data[offset] + 1;\n            }\n\n            const parsedPIDs = parsePMT(\n              data,\n              offset,\n              this.typeSupported,\n              isSampleAes,\n              this.observer,\n            );\n\n            // only update track id if track PID found while parsing PMT\n            // this is to avoid resetting the PID to -1 in case\n            // track PID transiently disappears from the stream\n            // this could happen in case of transient missing audio samples for example\n            // NOTE this is only the PID of the track as found in TS,\n            // but we are not using this for MP4 track IDs.\n            videoPid = parsedPIDs.videoPid;\n            if (videoPid > 0) {\n              videoTrack.pid = videoPid;\n              videoTrack.segmentCodec = parsedPIDs.segmentVideoCodec;\n            }\n\n            audioPid = parsedPIDs.audioPid;\n            if (audioPid > 0) {\n              audioTrack.pid = audioPid;\n              audioTrack.segmentCodec = parsedPIDs.segmentAudioCodec;\n            }\n            id3Pid = parsedPIDs.id3Pid;\n            if (id3Pid > 0) {\n              id3Track.pid = id3Pid;\n            }\n\n            if (unknownPID !== null && !pmtParsed) {\n              logger.warn(\n                `MPEG-TS PMT found at ${start} after unknown PID '${unknownPID}'. Backtracking to sync byte @${syncOffset} to parse all TS packets.`,\n              );\n              unknownPID = null;\n              // we set it to -188, the += 188 in the for loop will reset start to 0\n              start = syncOffset - 188;\n            }\n            pmtParsed = this.pmtParsed = true;\n            break;\n          }\n          case 0x11:\n          case 0x1fff:\n            break;\n          default:\n            unknownPID = pid;\n            break;\n        }\n      } else {\n        tsPacketErrors++;\n      }\n    }\n\n    if (tsPacketErrors > 0) {\n      emitParsingError(\n        this.observer,\n        new Error(\n          `Found ${tsPacketErrors} TS packet/s that do not start with 0x47`,\n        ),\n      );\n    }\n\n    videoTrack.pesData = videoData;\n    audioTrack.pesData = audioData;\n    id3Track.pesData = id3Data;\n\n    const demuxResult: DemuxerResult = {\n      audioTrack,\n      videoTrack,\n      id3Track,\n      textTrack,\n    };\n\n    if (flush) {\n      this.extractRemainingSamples(demuxResult);\n    }\n\n    return demuxResult;\n  }\n\n  public flush(): DemuxerResult | Promise<DemuxerResult> {\n    const { remainderData } = this;\n    this.remainderData = null;\n    let result: DemuxerResult;\n    if (remainderData) {\n      result = this.demux(remainderData, -1, false, true);\n    } else {\n      result = {\n        videoTrack: this._videoTrack as DemuxedVideoTrack,\n        audioTrack: this._audioTrack as DemuxedAudioTrack,\n        id3Track: this._id3Track as DemuxedMetadataTrack,\n        textTrack: this._txtTrack as DemuxedUserdataTrack,\n      };\n    }\n    this.extractRemainingSamples(result);\n    if (this.sampleAes) {\n      return this.decrypt(result, this.sampleAes);\n    }\n    return result;\n  }\n\n  private extractRemainingSamples(demuxResult: DemuxerResult) {\n    const { audioTrack, videoTrack, id3Track, textTrack } = demuxResult;\n    const videoData = videoTrack.pesData;\n    const audioData = audioTrack.pesData;\n    const id3Data = id3Track.pesData;\n    // try to parse last PES packets\n    let pes: PES | null;\n    if (videoData && (pes = parsePES(videoData))) {\n      this.videoParser.parseAVCPES(\n        videoTrack as DemuxedVideoTrack,\n        textTrack as DemuxedUserdataTrack,\n        pes,\n        true,\n        this._duration,\n      );\n      videoTrack.pesData = null;\n    } else {\n      // either avcData null or PES truncated, keep it for next frag parsing\n      videoTrack.pesData = videoData;\n    }\n\n    if (audioData && (pes = parsePES(audioData))) {\n      switch (audioTrack.segmentCodec) {\n        case 'aac':\n          this.parseAACPES(audioTrack, pes);\n          break;\n        case 'mp3':\n          this.parseMPEGPES(audioTrack, pes);\n          break;\n        case 'ac3':\n          if (__USE_M2TS_ADVANCED_CODECS__) {\n            this.parseAC3PES(audioTrack, pes);\n          }\n          break;\n      }\n      audioTrack.pesData = null;\n    } else {\n      if (audioData?.size) {\n        logger.log(\n          'last AAC PES packet truncated,might overlap between fragments',\n        );\n      }\n\n      // either audioData null or PES truncated, keep it for next frag parsing\n      audioTrack.pesData = audioData;\n    }\n\n    if (id3Data && (pes = parsePES(id3Data))) {\n      this.parseID3PES(id3Track, pes);\n      id3Track.pesData = null;\n    } else {\n      // either id3Data null or PES truncated, keep it for next frag parsing\n      id3Track.pesData = id3Data;\n    }\n  }\n\n  public demuxSampleAes(\n    data: Uint8Array,\n    keyData: KeyData,\n    timeOffset: number,\n  ): Promise<DemuxerResult> {\n    const demuxResult = this.demux(\n      data,\n      timeOffset,\n      true,\n      !this.config.progressive,\n    );\n    const sampleAes = (this.sampleAes = new SampleAesDecrypter(\n      this.observer,\n      this.config,\n      keyData,\n    ));\n    return this.decrypt(demuxResult, sampleAes);\n  }\n\n  private decrypt(\n    demuxResult: DemuxerResult,\n    sampleAes: SampleAesDecrypter,\n  ): Promise<DemuxerResult> {\n    return new Promise((resolve) => {\n      const { audioTrack, videoTrack } = demuxResult;\n      if (audioTrack.samples && audioTrack.segmentCodec === 'aac') {\n        sampleAes.decryptAacSamples(audioTrack.samples, 0, () => {\n          if (videoTrack.samples) {\n            sampleAes.decryptAvcSamples(videoTrack.samples, 0, 0, () => {\n              resolve(demuxResult);\n            });\n          } else {\n            resolve(demuxResult);\n          }\n        });\n      } else if (videoTrack.samples) {\n        sampleAes.decryptAvcSamples(videoTrack.samples, 0, 0, () => {\n          resolve(demuxResult);\n        });\n      }\n    });\n  }\n\n  public destroy() {\n    this._duration = 0;\n  }\n\n  private parseAACPES(track: DemuxedAudioTrack, pes: PES) {\n    let startOffset = 0;\n    const aacOverFlow = this.aacOverFlow;\n    let data = pes.data;\n    if (aacOverFlow) {\n      this.aacOverFlow = null;\n      const frameMissingBytes = aacOverFlow.missing;\n      const sampleLength = aacOverFlow.sample.unit.byteLength;\n      // logger.log(`AAC: append overflowing ${sampleLength} bytes to beginning of new PES`);\n      if (frameMissingBytes === -1) {\n        data = appendUint8Array(aacOverFlow.sample.unit, data);\n      } else {\n        const frameOverflowBytes = sampleLength - frameMissingBytes;\n        aacOverFlow.sample.unit.set(\n          data.subarray(0, frameMissingBytes),\n          frameOverflowBytes,\n        );\n        track.samples.push(aacOverFlow.sample);\n        startOffset = aacOverFlow.missing;\n      }\n    }\n    // look for ADTS header (0xFFFx)\n    let offset: number;\n    let len: number;\n    for (offset = startOffset, len = data.length; offset < len - 1; offset++) {\n      if (ADTS.isHeader(data, offset)) {\n        break;\n      }\n    }\n    // if ADTS header does not start straight from the beginning of the PES payload, raise an error\n    if (offset !== startOffset) {\n      let reason: string;\n      const recoverable = offset < len - 1;\n      if (recoverable) {\n        reason = `AAC PES did not start with ADTS header,offset:${offset}`;\n      } else {\n        reason = 'No ADTS header found in AAC PES';\n      }\n      emitParsingError(this.observer, new Error(reason), recoverable);\n      if (!recoverable) {\n        return;\n      }\n    }\n\n    ADTS.initTrackConfig(\n      track,\n      this.observer,\n      data,\n      offset,\n      this.audioCodec as string,\n    );\n\n    let pts: number;\n    if (pes.pts !== undefined) {\n      pts = pes.pts;\n    } else if (aacOverFlow) {\n      // if last AAC frame is overflowing, we should ensure timestamps are contiguous:\n      // first sample PTS should be equal to last sample PTS + frameDuration\n      const frameDuration = ADTS.getFrameDuration(track.samplerate as number);\n      pts = aacOverFlow.sample.pts + frameDuration;\n    } else {\n      logger.warn('[tsdemuxer]: AAC PES unknown PTS');\n      return;\n    }\n\n    // scan for aac samples\n    let frameIndex = 0;\n    let frame;\n    while (offset < len) {\n      frame = ADTS.appendFrame(track, data, offset, pts, frameIndex);\n      offset += frame.length;\n      if (!frame.missing) {\n        frameIndex++;\n        for (; offset < len - 1; offset++) {\n          if (ADTS.isHeader(data, offset)) {\n            break;\n          }\n        }\n      } else {\n        this.aacOverFlow = frame;\n        break;\n      }\n    }\n  }\n\n  private parseMPEGPES(track: DemuxedAudioTrack, pes: PES) {\n    const data = pes.data;\n    const length = data.length;\n    let frameIndex = 0;\n    let offset = 0;\n    const pts = pes.pts;\n    if (pts === undefined) {\n      logger.warn('[tsdemuxer]: MPEG PES unknown PTS');\n      return;\n    }\n\n    while (offset < length) {\n      if (MpegAudio.isHeader(data, offset)) {\n        const frame = MpegAudio.appendFrame(\n          track,\n          data,\n          offset,\n          pts,\n          frameIndex,\n        );\n        if (frame) {\n          offset += frame.length;\n          frameIndex++;\n        } else {\n          // logger.log('Unable to parse Mpeg audio frame');\n          break;\n        }\n      } else {\n        // nothing found, keep looking\n        offset++;\n      }\n    }\n  }\n\n  private parseAC3PES(track: DemuxedAudioTrack, pes: PES) {\n    if (__USE_M2TS_ADVANCED_CODECS__) {\n      const data = pes.data;\n      const pts = pes.pts;\n      if (pts === undefined) {\n        logger.warn('[tsdemuxer]: AC3 PES unknown PTS');\n        return;\n      }\n      const length = data.length;\n      let frameIndex = 0;\n      let offset = 0;\n      let parsed;\n\n      while (\n        offset < length &&\n        (parsed = AC3.appendFrame(track, data, offset, pts, frameIndex++)) > 0\n      ) {\n        offset += parsed;\n      }\n    }\n  }\n\n  private parseID3PES(id3Track: DemuxedMetadataTrack, pes: PES) {\n    if (pes.pts === undefined) {\n      logger.warn('[tsdemuxer]: ID3 PES unknown PTS');\n      return;\n    }\n    const id3Sample = Object.assign({}, pes as Required<PES>, {\n      type: this._videoTrack ? MetadataSchema.emsg : MetadataSchema.audioId3,\n      duration: Number.POSITIVE_INFINITY,\n    });\n    id3Track.samples.push(id3Sample);\n  }\n}\n\nfunction parsePID(data: Uint8Array, offset: number): number {\n  // pid is a 13-bit field starting at the last bit of TS[1]\n  return ((data[offset + 1] & 0x1f) << 8) + data[offset + 2];\n}\n\nfunction parsePAT(data: Uint8Array, offset: number): number {\n  // skip the PSI header and parse the first PMT entry\n  return ((data[offset + 10] & 0x1f) << 8) | data[offset + 11];\n}\n\nfunction parsePMT(\n  data: Uint8Array,\n  offset: number,\n  typeSupported: TypeSupported,\n  isSampleAes: boolean,\n  observer: HlsEventEmitter,\n) {\n  const result = {\n    audioPid: -1,\n    videoPid: -1,\n    id3Pid: -1,\n    segmentVideoCodec: 'avc',\n    segmentAudioCodec: 'aac',\n  };\n  const sectionLength = ((data[offset + 1] & 0x0f) << 8) | data[offset + 2];\n  const tableEnd = offset + 3 + sectionLength - 4;\n  // to determine where the table is, we have to figure out how\n  // long the program info descriptors are\n  const programInfoLength =\n    ((data[offset + 10] & 0x0f) << 8) | data[offset + 11];\n  // advance the offset to the first entry in the mapping table\n  offset += 12 + programInfoLength;\n  while (offset < tableEnd) {\n    const pid = parsePID(data, offset);\n    const esInfoLength = ((data[offset + 3] & 0x0f) << 8) | data[offset + 4];\n    switch (data[offset]) {\n      case 0xcf: // SAMPLE-AES AAC\n        if (!isSampleAes) {\n          logEncryptedSamplesFoundInUnencryptedStream('ADTS AAC');\n          break;\n        }\n      /* falls through */\n      case 0x0f: // ISO/IEC 13818-7 ADTS AAC (MPEG-2 lower bit-rate audio)\n        // logger.log('AAC PID:'  + pid);\n        if (result.audioPid === -1) {\n          result.audioPid = pid;\n        }\n\n        break;\n\n      // Packetized metadata (ID3)\n      case 0x15:\n        // logger.log('ID3 PID:'  + pid);\n        if (result.id3Pid === -1) {\n          result.id3Pid = pid;\n        }\n\n        break;\n\n      case 0xdb: // SAMPLE-AES AVC\n        if (!isSampleAes) {\n          logEncryptedSamplesFoundInUnencryptedStream('H.264');\n          break;\n        }\n      /* falls through */\n      case 0x1b: // ITU-T Rec. H.264 and ISO/IEC 14496-10 (lower bit-rate video)\n        // logger.log('AVC PID:'  + pid);\n        if (result.videoPid === -1) {\n          result.videoPid = pid;\n          result.segmentVideoCodec = 'avc';\n        }\n\n        break;\n\n      // ISO/IEC 11172-3 (MPEG-1 audio)\n      // or ISO/IEC 13818-3 (MPEG-2 halved sample rate audio)\n      case 0x03:\n      case 0x04:\n        // logger.log('MPEG PID:'  + pid);\n        if (!typeSupported.mpeg && !typeSupported.mp3) {\n          logger.log('MPEG audio found, not supported in this browser');\n        } else if (result.audioPid === -1) {\n          result.audioPid = pid;\n          result.segmentAudioCodec = 'mp3';\n        }\n        break;\n\n      case 0xc1: // SAMPLE-AES AC3\n        if (!isSampleAes) {\n          logEncryptedSamplesFoundInUnencryptedStream('AC-3');\n          break;\n        }\n      /* falls through */\n      case 0x81:\n        if (__USE_M2TS_ADVANCED_CODECS__) {\n          if (!typeSupported.ac3) {\n            logger.log('AC-3 audio found, not supported in this browser');\n          } else if (result.audioPid === -1) {\n            result.audioPid = pid;\n            result.segmentAudioCodec = 'ac3';\n          }\n        } else {\n          logger.warn('AC-3 in M2TS support not included in build');\n        }\n        break;\n\n      case 0x06:\n        // stream_type 6 can mean a lot of different things in case of DVB.\n        // We need to look at the descriptors. Right now, we're only interested\n        // in AC-3 audio, so we do the descriptor parsing only when we don't have\n        // an audio PID yet.\n        if (result.audioPid === -1 && esInfoLength > 0) {\n          let parsePos = offset + 5;\n          let remaining = esInfoLength;\n\n          while (remaining > 2) {\n            const descriptorId = data[parsePos];\n\n            switch (descriptorId) {\n              case 0x6a: // DVB Descriptor for AC-3\n                if (__USE_M2TS_ADVANCED_CODECS__) {\n                  if (typeSupported.ac3 !== true) {\n                    logger.log(\n                      'AC-3 audio found, not supported in this browser for now',\n                    );\n                  } else {\n                    result.audioPid = pid;\n                    result.segmentAudioCodec = 'ac3';\n                  }\n                } else {\n                  logger.warn('AC-3 in M2TS support not included in build');\n                }\n                break;\n            }\n\n            const descriptorLen = data[parsePos + 1] + 2;\n            parsePos += descriptorLen;\n            remaining -= descriptorLen;\n          }\n        }\n        break;\n\n      case 0xc2: // SAMPLE-AES EC3\n      /* falls through */\n      case 0x87:\n        emitParsingError(observer, new Error('Unsupported EC-3 in M2TS found'));\n        return result;\n\n      case 0x24:\n        emitParsingError(observer, new Error('Unsupported HEVC in M2TS found'));\n        return result;\n\n      default:\n        // logger.log('unknown stream type:' + data[offset]);\n        break;\n    }\n    // move to the next table entry\n    // skip past the elementary stream descriptors, if present\n    offset += esInfoLength + 5;\n  }\n  return result;\n}\n\nfunction emitParsingError(\n  observer: HlsEventEmitter,\n  error: Error,\n  levelRetry?: boolean,\n) {\n  logger.warn(`parsing error: ${error.message}`);\n  observer.emit(Events.ERROR, Events.ERROR, {\n    type: ErrorTypes.MEDIA_ERROR,\n    details: ErrorDetails.FRAG_PARSING_ERROR,\n    fatal: false,\n    levelRetry,\n    error,\n    reason: error.message,\n  });\n}\n\nfunction logEncryptedSamplesFoundInUnencryptedStream(type: string) {\n  logger.log(`${type} with AES-128-CBC encryption found in unencrypted stream`);\n}\n\nfunction parsePES(stream: ElementaryStreamData): PES | null {\n  let i = 0;\n  let frag: Uint8Array;\n  let pesLen: number;\n  let pesHdrLen: number;\n  let pesPts: number | undefined;\n  let pesDts: number | undefined;\n  const data = stream.data;\n  // safety check\n  if (!stream || stream.size === 0) {\n    return null;\n  }\n\n  // we might need up to 19 bytes to read PES header\n  // if first chunk of data is less than 19 bytes, let's merge it with following ones until we get 19 bytes\n  // usually only one merge is needed (and this is rare ...)\n  while (data[0].length < 19 && data.length > 1) {\n    data[0] = appendUint8Array(data[0], data[1]);\n    data.splice(1, 1);\n  }\n  // retrieve PTS/DTS from first fragment\n  frag = data[0];\n  const pesPrefix = (frag[0] << 16) + (frag[1] << 8) + frag[2];\n  if (pesPrefix === 1) {\n    pesLen = (frag[4] << 8) + frag[5];\n    // if PES parsed length is not zero and greater than total received length, stop parsing. PES might be truncated\n    // minus 6 : PES header size\n    if (pesLen && pesLen > stream.size - 6) {\n      return null;\n    }\n\n    const pesFlags = frag[7];\n    if (pesFlags & 0xc0) {\n      /* PES header described here : http://dvd.sourceforge.net/dvdinfo/pes-hdr.html\n          as PTS / DTS is 33 bit we cannot use bitwise operator in JS,\n          as Bitwise operators treat their operands as a sequence of 32 bits */\n      pesPts =\n        (frag[9] & 0x0e) * 536870912 + // 1 << 29\n        (frag[10] & 0xff) * 4194304 + // 1 << 22\n        (frag[11] & 0xfe) * 16384 + // 1 << 14\n        (frag[12] & 0xff) * 128 + // 1 << 7\n        (frag[13] & 0xfe) / 2;\n\n      if (pesFlags & 0x40) {\n        pesDts =\n          (frag[14] & 0x0e) * 536870912 + // 1 << 29\n          (frag[15] & 0xff) * 4194304 + // 1 << 22\n          (frag[16] & 0xfe) * 16384 + // 1 << 14\n          (frag[17] & 0xff) * 128 + // 1 << 7\n          (frag[18] & 0xfe) / 2;\n\n        if (pesPts - pesDts > 60 * 90000) {\n          logger.warn(\n            `${Math.round(\n              (pesPts - pesDts) / 90000,\n            )}s delta between PTS and DTS, align them`,\n          );\n          pesPts = pesDts;\n        }\n      } else {\n        pesDts = pesPts;\n      }\n    }\n    pesHdrLen = frag[8];\n    // 9 bytes : 6 bytes for PES header + 3 bytes for PES extension\n    let payloadStartOffset = pesHdrLen + 9;\n    if (stream.size <= payloadStartOffset) {\n      return null;\n    }\n    stream.size -= payloadStartOffset;\n    // reassemble PES packet\n    const pesData = new Uint8Array(stream.size);\n    for (let j = 0, dataLen = data.length; j < dataLen; j++) {\n      frag = data[j];\n      let len = frag.byteLength;\n      if (payloadStartOffset) {\n        if (payloadStartOffset > len) {\n          // trim full frag if PES header bigger than frag\n          payloadStartOffset -= len;\n          continue;\n        } else {\n          // trim partial frag if PES header smaller than frag\n          frag = frag.subarray(payloadStartOffset);\n          len -= payloadStartOffset;\n          payloadStartOffset = 0;\n        }\n      }\n      pesData.set(frag, i);\n      i += len;\n    }\n    if (pesLen) {\n      // payload size : remove PES header + PES extension\n      pesLen -= pesHdrLen + 3;\n    }\n    return { data: pesData, pts: pesPts, dts: pesDts, len: pesLen };\n  }\n  return null;\n}\n\nexport default TSDemuxer;\n", "/**\n * MP3 demuxer\n */\nimport BaseAudioDemuxer from './base-audio-demuxer';\nimport { getID3Data, getTimeStamp } from '../id3';\nimport { getAudioBSID } from './dolby';\nimport { logger } from '../../utils/logger';\nimport * as MpegAudio from './mpegaudio';\n\nclass MP3Demuxer extends BaseAudioDemuxer {\n  resetInitSegment(\n    initSegment: Uint8Array | undefined,\n    audioCodec: string | undefined,\n    videoCodec: string | undefined,\n    trackDuration: number,\n  ) {\n    super.resetInitSegment(initSegment, audioCodec, videoCodec, trackDuration);\n    this._audioTrack = {\n      container: 'audio/mpeg',\n      type: 'audio',\n      id: 2,\n      pid: -1,\n      sequenceNumber: 0,\n      segmentCodec: 'mp3',\n      samples: [],\n      manifestCodec: audioCodec,\n      duration: trackDuration,\n      inputTimeScale: 90000,\n      dropped: 0,\n    };\n  }\n\n  static probe(data: Uint8Array | undefined): boolean {\n    if (!data) {\n      return false;\n    }\n\n    // check if data contains ID3 timestamp and MPEG sync word\n    // Look for MPEG header | 1111 1111 | 111X XYZX | where X can be either 0 or 1 and Y or Z should be 1\n    // Layer bits (position 14 and 15) in header should be always different from 0 (Layer I or Layer II or Layer III)\n    // More info http://www.mp3-tech.org/programmer/frame_header.html\n    const id3Data = getID3Data(data, 0);\n    let offset = id3Data?.length || 0;\n\n    // Check for ac-3|ec-3 sync bytes and return false if present\n    if (\n      id3Data &&\n      data[offset] === 0x0b &&\n      data[offset + 1] === 0x77 &&\n      getTimeStamp(id3Data) !== undefined &&\n      // check the bsid to confirm ac-3 or ec-3 (not mp3)\n      getAudioBSID(data, offset) <= 16\n    ) {\n      return false;\n    }\n\n    for (let length = data.length; offset < length; offset++) {\n      if (MpegAudio.probe(data, offset)) {\n        logger.log('MPEG Audio sync word found !');\n        return true;\n      }\n    }\n    return false;\n  }\n\n  canParse(data, offset) {\n    return MpegAudio.canParse(data, offset);\n  }\n\n  appendFrame(track, data, offset) {\n    if (this.basePTS === null) {\n      return;\n    }\n    return MpegAudio.appendFrame(\n      track,\n      data,\n      offset,\n      this.basePTS,\n      this.frameIndex,\n    );\n  }\n}\n\nexport default MP3Demuxer;\n", "/**\n *  AAC helper\n */\n\nclass AAC {\n  static getSilentFrame(\n    codec?: string,\n    channelCount?: number,\n  ): Uint8Array | undefined {\n    switch (codec) {\n      case 'mp4a.40.2':\n        if (channelCount === 1) {\n          return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x23, 0x80]);\n        } else if (channelCount === 2) {\n          return new Uint8Array([\n            0x21, 0x00, 0x49, 0x90, 0x02, 0x19, 0x00, 0x23, 0x80,\n          ]);\n        } else if (channelCount === 3) {\n          return new Uint8Array([\n            0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64,\n            0x00, 0x8e,\n          ]);\n        } else if (channelCount === 4) {\n          return new Uint8Array([\n            0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64,\n            0x00, 0x80, 0x2c, 0x80, 0x08, 0x02, 0x38,\n          ]);\n        } else if (channelCount === 5) {\n          return new Uint8Array([\n            0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64,\n            0x00, 0x82, 0x30, 0x04, 0x99, 0x00, 0x21, 0x90, 0x02, 0x38,\n          ]);\n        } else if (channelCount === 6) {\n          return new Uint8Array([\n            0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64,\n            0x00, 0x82, 0x30, 0x04, 0x99, 0x00, 0x21, 0x90, 0x02, 0x00, 0xb2,\n            0x00, 0x20, 0x08, 0xe0,\n          ]);\n        }\n\n        break;\n      // handle HE-AAC below (mp4a.40.5 / mp4a.40.29)\n      default:\n        if (channelCount === 1) {\n          // ffmpeg -y -f lavfi -i \"aevalsrc=0:d=0.05\" -c:a libfdk_aac -profile:a aac_he -b:a 4k output.aac && hexdump -v -e '16/1 \"0x%x,\" \"\\n\"' -v output.aac\n          return new Uint8Array([\n            0x1, 0x40, 0x22, 0x80, 0xa3, 0x4e, 0xe6, 0x80, 0xba, 0x8, 0x0, 0x0,\n            0x0, 0x1c, 0x6, 0xf1, 0xc1, 0xa, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,\n            0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,\n            0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,\n            0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,\n            0x5a, 0x5e,\n          ]);\n        } else if (channelCount === 2) {\n          // ffmpeg -y -f lavfi -i \"aevalsrc=0|0:d=0.05\" -c:a libfdk_aac -profile:a aac_he_v2 -b:a 4k output.aac && hexdump -v -e '16/1 \"0x%x,\" \"\\n\"' -v output.aac\n          return new Uint8Array([\n            0x1, 0x40, 0x22, 0x80, 0xa3, 0x5e, 0xe6, 0x80, 0xba, 0x8, 0x0, 0x0,\n            0x0, 0x0, 0x95, 0x0, 0x6, 0xf1, 0xa1, 0xa, 0x5a, 0x5a, 0x5a, 0x5a,\n            0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,\n            0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,\n            0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,\n            0x5a, 0x5e,\n          ]);\n        } else if (channelCount === 3) {\n          // ffmpeg -y -f lavfi -i \"aevalsrc=0|0|0:d=0.05\" -c:a libfdk_aac -profile:a aac_he_v2 -b:a 4k output.aac && hexdump -v -e '16/1 \"0x%x,\" \"\\n\"' -v output.aac\n          return new Uint8Array([\n            0x1, 0x40, 0x22, 0x80, 0xa3, 0x5e, 0xe6, 0x80, 0xba, 0x8, 0x0, 0x0,\n            0x0, 0x0, 0x95, 0x0, 0x6, 0xf1, 0xa1, 0xa, 0x5a, 0x5a, 0x5a, 0x5a,\n            0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,\n            0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,\n            0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,\n            0x5a, 0x5e,\n          ]);\n        }\n        break;\n    }\n    return undefined;\n  }\n}\n\nexport default AAC;\n", "/**\n * Generate MP4 Box\n */\n\nimport { appendUint8Array } from '../utils/mp4-tools';\n\ntype HdlrTypes = {\n  video: Uint8Array;\n  audio: Uint8Array;\n};\n\nconst UINT32_MAX = Math.pow(2, 32) - 1;\n\nclass MP4 {\n  public static types: Record<string, number[]>;\n  private static HDLR_TYPES: HdlrTypes;\n  private static STTS: Uint8Array;\n  private static STSC: Uint8Array;\n  private static STCO: Uint8Array;\n  private static STSZ: Uint8Array;\n  private static VMHD: Uint8Array;\n  private static SMHD: Uint8Array;\n  private static STSD: Uint8Array;\n  private static FTYP: Uint8Array;\n  private static DINF: Uint8Array;\n\n  static init() {\n    MP4.types = {\n      avc1: [], // codingname\n      avcC: [],\n      btrt: [],\n      dinf: [],\n      dref: [],\n      esds: [],\n      ftyp: [],\n      hdlr: [],\n      mdat: [],\n      mdhd: [],\n      mdia: [],\n      mfhd: [],\n      minf: [],\n      moof: [],\n      moov: [],\n      mp4a: [],\n      '.mp3': [],\n      dac3: [],\n      'ac-3': [],\n      mvex: [],\n      mvhd: [],\n      pasp: [],\n      sdtp: [],\n      stbl: [],\n      stco: [],\n      stsc: [],\n      stsd: [],\n      stsz: [],\n      stts: [],\n      tfdt: [],\n      tfhd: [],\n      traf: [],\n      trak: [],\n      trun: [],\n      trex: [],\n      tkhd: [],\n      vmhd: [],\n      smhd: [],\n    };\n\n    let i: string;\n    for (i in MP4.types) {\n      if (MP4.types.hasOwnProperty(i)) {\n        MP4.types[i] = [\n          i.charCodeAt(0),\n          i.charCodeAt(1),\n          i.charCodeAt(2),\n          i.charCodeAt(3),\n        ];\n      }\n    }\n\n    const videoHdlr = new Uint8Array([\n      0x00, // version 0\n      0x00,\n      0x00,\n      0x00, // flags\n      0x00,\n      0x00,\n      0x00,\n      0x00, // pre_defined\n      0x76,\n      0x69,\n      0x64,\n      0x65, // handler_type: 'vide'\n      0x00,\n      0x00,\n      0x00,\n      0x00, // reserved\n      0x00,\n      0x00,\n      0x00,\n      0x00, // reserved\n      0x00,\n      0x00,\n      0x00,\n      0x00, // reserved\n      0x56,\n      0x69,\n      0x64,\n      0x65,\n      0x6f,\n      0x48,\n      0x61,\n      0x6e,\n      0x64,\n      0x6c,\n      0x65,\n      0x72,\n      0x00, // name: 'VideoHandler'\n    ]);\n\n    const audioHdlr = new Uint8Array([\n      0x00, // version 0\n      0x00,\n      0x00,\n      0x00, // flags\n      0x00,\n      0x00,\n      0x00,\n      0x00, // pre_defined\n      0x73,\n      0x6f,\n      0x75,\n      0x6e, // handler_type: 'soun'\n      0x00,\n      0x00,\n      0x00,\n      0x00, // reserved\n      0x00,\n      0x00,\n      0x00,\n      0x00, // reserved\n      0x00,\n      0x00,\n      0x00,\n      0x00, // reserved\n      0x53,\n      0x6f,\n      0x75,\n      0x6e,\n      0x64,\n      0x48,\n      0x61,\n      0x6e,\n      0x64,\n      0x6c,\n      0x65,\n      0x72,\n      0x00, // name: 'SoundHandler'\n    ]);\n\n    MP4.HDLR_TYPES = {\n      video: videoHdlr,\n      audio: audioHdlr,\n    };\n\n    const dref = new Uint8Array([\n      0x00, // version 0\n      0x00,\n      0x00,\n      0x00, // flags\n      0x00,\n      0x00,\n      0x00,\n      0x01, // entry_count\n      0x00,\n      0x00,\n      0x00,\n      0x0c, // entry_size\n      0x75,\n      0x72,\n      0x6c,\n      0x20, // 'url' type\n      0x00, // version 0\n      0x00,\n      0x00,\n      0x01, // entry_flags\n    ]);\n\n    const stco = new Uint8Array([\n      0x00, // version\n      0x00,\n      0x00,\n      0x00, // flags\n      0x00,\n      0x00,\n      0x00,\n      0x00, // entry_count\n    ]);\n\n    MP4.STTS = MP4.STSC = MP4.STCO = stco;\n\n    MP4.STSZ = new Uint8Array([\n      0x00, // version\n      0x00,\n      0x00,\n      0x00, // flags\n      0x00,\n      0x00,\n      0x00,\n      0x00, // sample_size\n      0x00,\n      0x00,\n      0x00,\n      0x00, // sample_count\n    ]);\n    MP4.VMHD = new Uint8Array([\n      0x00, // version\n      0x00,\n      0x00,\n      0x01, // flags\n      0x00,\n      0x00, // graphicsmode\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00, // opcolor\n    ]);\n    MP4.SMHD = new Uint8Array([\n      0x00, // version\n      0x00,\n      0x00,\n      0x00, // flags\n      0x00,\n      0x00, // balance\n      0x00,\n      0x00, // reserved\n    ]);\n\n    MP4.STSD = new Uint8Array([\n      0x00, // version 0\n      0x00,\n      0x00,\n      0x00, // flags\n      0x00,\n      0x00,\n      0x00,\n      0x01,\n    ]); // entry_count\n\n    const majorBrand = new Uint8Array([105, 115, 111, 109]); // isom\n    const avc1Brand = new Uint8Array([97, 118, 99, 49]); // avc1\n    const minorVersion = new Uint8Array([0, 0, 0, 1]);\n\n    MP4.FTYP = MP4.box(\n      MP4.types.ftyp,\n      majorBrand,\n      minorVersion,\n      majorBrand,\n      avc1Brand,\n    );\n    MP4.DINF = MP4.box(MP4.types.dinf, MP4.box(MP4.types.dref, dref));\n  }\n\n  static box(type, ...payload: Uint8Array[]) {\n    let size = 8;\n    let i = payload.length;\n    const len = i;\n    // calculate the total size we need to allocate\n    while (i--) {\n      size += payload[i].byteLength;\n    }\n\n    const result = new Uint8Array(size);\n    result[0] = (size >> 24) & 0xff;\n    result[1] = (size >> 16) & 0xff;\n    result[2] = (size >> 8) & 0xff;\n    result[3] = size & 0xff;\n    result.set(type, 4);\n    // copy the payload into the result\n    for (i = 0, size = 8; i < len; i++) {\n      // copy payload[i] array @ offset size\n      result.set(payload[i], size);\n      size += payload[i].byteLength;\n    }\n    return result;\n  }\n\n  static hdlr(type) {\n    return MP4.box(MP4.types.hdlr, MP4.HDLR_TYPES[type]);\n  }\n\n  static mdat(data) {\n    return MP4.box(MP4.types.mdat, data);\n  }\n\n  static mdhd(timescale, duration) {\n    duration *= timescale;\n    const upperWordDuration = Math.floor(duration / (UINT32_MAX + 1));\n    const lowerWordDuration = Math.floor(duration % (UINT32_MAX + 1));\n    return MP4.box(\n      MP4.types.mdhd,\n      new Uint8Array([\n        0x01, // version 1\n        0x00,\n        0x00,\n        0x00, // flags\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x02, // creation_time\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x03, // modification_time\n        (timescale >> 24) & 0xff,\n        (timescale >> 16) & 0xff,\n        (timescale >> 8) & 0xff,\n        timescale & 0xff, // timescale\n        upperWordDuration >> 24,\n        (upperWordDuration >> 16) & 0xff,\n        (upperWordDuration >> 8) & 0xff,\n        upperWordDuration & 0xff,\n        lowerWordDuration >> 24,\n        (lowerWordDuration >> 16) & 0xff,\n        (lowerWordDuration >> 8) & 0xff,\n        lowerWordDuration & 0xff,\n        0x55,\n        0xc4, // 'und' language (undetermined)\n        0x00,\n        0x00,\n      ]),\n    );\n  }\n\n  static mdia(track) {\n    return MP4.box(\n      MP4.types.mdia,\n      MP4.mdhd(track.timescale, track.duration),\n      MP4.hdlr(track.type),\n      MP4.minf(track),\n    );\n  }\n\n  static mfhd(sequenceNumber) {\n    return MP4.box(\n      MP4.types.mfhd,\n      new Uint8Array([\n        0x00,\n        0x00,\n        0x00,\n        0x00, // flags\n        sequenceNumber >> 24,\n        (sequenceNumber >> 16) & 0xff,\n        (sequenceNumber >> 8) & 0xff,\n        sequenceNumber & 0xff, // sequence_number\n      ]),\n    );\n  }\n\n  static minf(track) {\n    if (track.type === 'audio') {\n      return MP4.box(\n        MP4.types.minf,\n        MP4.box(MP4.types.smhd, MP4.SMHD),\n        MP4.DINF,\n        MP4.stbl(track),\n      );\n    } else {\n      return MP4.box(\n        MP4.types.minf,\n        MP4.box(MP4.types.vmhd, MP4.VMHD),\n        MP4.DINF,\n        MP4.stbl(track),\n      );\n    }\n  }\n\n  static moof(sn, baseMediaDecodeTime, track) {\n    return MP4.box(\n      MP4.types.moof,\n      MP4.mfhd(sn),\n      MP4.traf(track, baseMediaDecodeTime),\n    );\n  }\n\n  static moov(tracks) {\n    let i = tracks.length;\n    const boxes: Uint8Array[] = [];\n\n    while (i--) {\n      boxes[i] = MP4.trak(tracks[i]);\n    }\n\n    return MP4.box.apply(\n      null,\n      [MP4.types.moov, MP4.mvhd(tracks[0].timescale, tracks[0].duration)]\n        .concat(boxes)\n        .concat(MP4.mvex(tracks)),\n    );\n  }\n\n  static mvex(tracks) {\n    let i = tracks.length;\n    const boxes: Uint8Array[] = [];\n\n    while (i--) {\n      boxes[i] = MP4.trex(tracks[i]);\n    }\n\n    return MP4.box.apply(null, [MP4.types.mvex, ...boxes]);\n  }\n\n  static mvhd(timescale, duration) {\n    duration *= timescale;\n    const upperWordDuration = Math.floor(duration / (UINT32_MAX + 1));\n    const lowerWordDuration = Math.floor(duration % (UINT32_MAX + 1));\n    const bytes = new Uint8Array([\n      0x01, // version 1\n      0x00,\n      0x00,\n      0x00, // flags\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x02, // creation_time\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x03, // modification_time\n      (timescale >> 24) & 0xff,\n      (timescale >> 16) & 0xff,\n      (timescale >> 8) & 0xff,\n      timescale & 0xff, // timescale\n      upperWordDuration >> 24,\n      (upperWordDuration >> 16) & 0xff,\n      (upperWordDuration >> 8) & 0xff,\n      upperWordDuration & 0xff,\n      lowerWordDuration >> 24,\n      (lowerWordDuration >> 16) & 0xff,\n      (lowerWordDuration >> 8) & 0xff,\n      lowerWordDuration & 0xff,\n      0x00,\n      0x01,\n      0x00,\n      0x00, // 1.0 rate\n      0x01,\n      0x00, // 1.0 volume\n      0x00,\n      0x00, // reserved\n      0x00,\n      0x00,\n      0x00,\n      0x00, // reserved\n      0x00,\n      0x00,\n      0x00,\n      0x00, // reserved\n      0x00,\n      0x01,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x01,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x40,\n      0x00,\n      0x00,\n      0x00, // transformation: unity matrix\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00, // pre_defined\n      0xff,\n      0xff,\n      0xff,\n      0xff, // next_track_ID\n    ]);\n    return MP4.box(MP4.types.mvhd, bytes);\n  }\n\n  static sdtp(track) {\n    const samples = track.samples || [];\n    const bytes = new Uint8Array(4 + samples.length);\n    let i;\n    let flags;\n    // leave the full box header (4 bytes) all zero\n    // write the sample table\n    for (i = 0; i < samples.length; i++) {\n      flags = samples[i].flags;\n      bytes[i + 4] =\n        (flags.dependsOn << 4) |\n        (flags.isDependedOn << 2) |\n        flags.hasRedundancy;\n    }\n\n    return MP4.box(MP4.types.sdtp, bytes);\n  }\n\n  static stbl(track) {\n    return MP4.box(\n      MP4.types.stbl,\n      MP4.stsd(track),\n      MP4.box(MP4.types.stts, MP4.STTS),\n      MP4.box(MP4.types.stsc, MP4.STSC),\n      MP4.box(MP4.types.stsz, MP4.STSZ),\n      MP4.box(MP4.types.stco, MP4.STCO),\n    );\n  }\n\n  static avc1(track) {\n    let sps: number[] = [];\n    let pps: number[] = [];\n    let i;\n    let data;\n    let len;\n    // assemble the SPSs\n\n    for (i = 0; i < track.sps.length; i++) {\n      data = track.sps[i];\n      len = data.byteLength;\n      sps.push((len >>> 8) & 0xff);\n      sps.push(len & 0xff);\n\n      // SPS\n      sps = sps.concat(Array.prototype.slice.call(data));\n    }\n\n    // assemble the PPSs\n    for (i = 0; i < track.pps.length; i++) {\n      data = track.pps[i];\n      len = data.byteLength;\n      pps.push((len >>> 8) & 0xff);\n      pps.push(len & 0xff);\n\n      pps = pps.concat(Array.prototype.slice.call(data));\n    }\n\n    const avcc = MP4.box(\n      MP4.types.avcC,\n      new Uint8Array(\n        [\n          0x01, // version\n          sps[3], // profile\n          sps[4], // profile compat\n          sps[5], // level\n          0xfc | 3, // lengthSizeMinusOne, hard-coded to 4 bytes\n          0xe0 | track.sps.length, // 3bit reserved (111) + numOfSequenceParameterSets\n        ]\n          .concat(sps)\n          .concat([\n            track.pps.length, // numOfPictureParameterSets\n          ])\n          .concat(pps),\n      ),\n    ); // \"PPS\"\n    const width = track.width;\n    const height = track.height;\n    const hSpacing = track.pixelRatio[0];\n    const vSpacing = track.pixelRatio[1];\n\n    return MP4.box(\n      MP4.types.avc1,\n      new Uint8Array([\n        0x00,\n        0x00,\n        0x00, // reserved\n        0x00,\n        0x00,\n        0x00, // reserved\n        0x00,\n        0x01, // data_reference_index\n        0x00,\n        0x00, // pre_defined\n        0x00,\n        0x00, // reserved\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00, // pre_defined\n        (width >> 8) & 0xff,\n        width & 0xff, // width\n        (height >> 8) & 0xff,\n        height & 0xff, // height\n        0x00,\n        0x48,\n        0x00,\n        0x00, // horizresolution\n        0x00,\n        0x48,\n        0x00,\n        0x00, // vertresolution\n        0x00,\n        0x00,\n        0x00,\n        0x00, // reserved\n        0x00,\n        0x01, // frame_count\n        0x12,\n        0x64,\n        0x61,\n        0x69,\n        0x6c, // dailymotion/hls.js\n        0x79,\n        0x6d,\n        0x6f,\n        0x74,\n        0x69,\n        0x6f,\n        0x6e,\n        0x2f,\n        0x68,\n        0x6c,\n        0x73,\n        0x2e,\n        0x6a,\n        0x73,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00, // compressorname\n        0x00,\n        0x18, // depth = 24\n        0x11,\n        0x11,\n      ]), // pre_defined = -1\n      avcc,\n      MP4.box(\n        MP4.types.btrt,\n        new Uint8Array([\n          0x00,\n          0x1c,\n          0x9c,\n          0x80, // bufferSizeDB\n          0x00,\n          0x2d,\n          0xc6,\n          0xc0, // maxBitrate\n          0x00,\n          0x2d,\n          0xc6,\n          0xc0,\n        ]),\n      ), // avgBitrate\n      MP4.box(\n        MP4.types.pasp,\n        new Uint8Array([\n          hSpacing >> 24, // hSpacing\n          (hSpacing >> 16) & 0xff,\n          (hSpacing >> 8) & 0xff,\n          hSpacing & 0xff,\n          vSpacing >> 24, // vSpacing\n          (vSpacing >> 16) & 0xff,\n          (vSpacing >> 8) & 0xff,\n          vSpacing & 0xff,\n        ]),\n      ),\n    );\n  }\n\n  static esds(track) {\n    const configlen = track.config.length;\n    return new Uint8Array(\n      [\n        0x00, // version 0\n        0x00,\n        0x00,\n        0x00, // flags\n\n        0x03, // descriptor_type\n        0x17 + configlen, // length\n        0x00,\n        0x01, // es_id\n        0x00, // stream_priority\n\n        0x04, // descriptor_type\n        0x0f + configlen, // length\n        0x40, // codec : mpeg4_audio\n        0x15, // stream_type\n        0x00,\n        0x00,\n        0x00, // buffer_size\n        0x00,\n        0x00,\n        0x00,\n        0x00, // maxBitrate\n        0x00,\n        0x00,\n        0x00,\n        0x00, // avgBitrate\n\n        0x05, // descriptor_type\n      ]\n        .concat([configlen])\n        .concat(track.config)\n        .concat([0x06, 0x01, 0x02]),\n    ); // GASpecificConfig)); // length + audio config descriptor\n  }\n\n  static audioStsd(track) {\n    const samplerate = track.samplerate;\n    return new Uint8Array([\n      0x00,\n      0x00,\n      0x00, // reserved\n      0x00,\n      0x00,\n      0x00, // reserved\n      0x00,\n      0x01, // data_reference_index\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00,\n      0x00, // reserved\n      0x00,\n      track.channelCount, // channelcount\n      0x00,\n      0x10, // sampleSize:16bits\n      0x00,\n      0x00,\n      0x00,\n      0x00, // reserved2\n      (samplerate >> 8) & 0xff,\n      samplerate & 0xff, //\n      0x00,\n      0x00,\n    ]);\n  }\n\n  static mp4a(track) {\n    return MP4.box(\n      MP4.types.mp4a,\n      MP4.audioStsd(track),\n      MP4.box(MP4.types.esds, MP4.esds(track)),\n    );\n  }\n\n  static mp3(track) {\n    return MP4.box(MP4.types['.mp3'], MP4.audioStsd(track));\n  }\n\n  static ac3(track) {\n    return MP4.box(\n      MP4.types['ac-3'],\n      MP4.audioStsd(track),\n      MP4.box(MP4.types.dac3, track.config),\n    );\n  }\n\n  static stsd(track) {\n    if (track.type === 'audio') {\n      if (track.segmentCodec === 'mp3' && track.codec === 'mp3') {\n        return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp3(track));\n      }\n      if (track.segmentCodec === 'ac3') {\n        return MP4.box(MP4.types.stsd, MP4.STSD, MP4.ac3(track));\n      }\n      return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp4a(track));\n    } else {\n      return MP4.box(MP4.types.stsd, MP4.STSD, MP4.avc1(track));\n    }\n  }\n\n  static tkhd(track) {\n    const id = track.id;\n    const duration = track.duration * track.timescale;\n    const width = track.width;\n    const height = track.height;\n    const upperWordDuration = Math.floor(duration / (UINT32_MAX + 1));\n    const lowerWordDuration = Math.floor(duration % (UINT32_MAX + 1));\n    return MP4.box(\n      MP4.types.tkhd,\n      new Uint8Array([\n        0x01, // version 1\n        0x00,\n        0x00,\n        0x07, // flags\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x02, // creation_time\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x03, // modification_time\n        (id >> 24) & 0xff,\n        (id >> 16) & 0xff,\n        (id >> 8) & 0xff,\n        id & 0xff, // track_ID\n        0x00,\n        0x00,\n        0x00,\n        0x00, // reserved\n        upperWordDuration >> 24,\n        (upperWordDuration >> 16) & 0xff,\n        (upperWordDuration >> 8) & 0xff,\n        upperWordDuration & 0xff,\n        lowerWordDuration >> 24,\n        (lowerWordDuration >> 16) & 0xff,\n        (lowerWordDuration >> 8) & 0xff,\n        lowerWordDuration & 0xff,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00, // reserved\n        0x00,\n        0x00, // layer\n        0x00,\n        0x00, // alternate_group\n        0x00,\n        0x00, // non-audio track volume\n        0x00,\n        0x00, // reserved\n        0x00,\n        0x01,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x01,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x00,\n        0x40,\n        0x00,\n        0x00,\n        0x00, // transformation: unity matrix\n        (width >> 8) & 0xff,\n        width & 0xff,\n        0x00,\n        0x00, // width\n        (height >> 8) & 0xff,\n        height & 0xff,\n        0x00,\n        0x00, // height\n      ]),\n    );\n  }\n\n  static traf(track, baseMediaDecodeTime) {\n    const sampleDependencyTable = MP4.sdtp(track);\n    const id = track.id;\n    const upperWordBaseMediaDecodeTime = Math.floor(\n      baseMediaDecodeTime / (UINT32_MAX + 1),\n    );\n    const lowerWordBaseMediaDecodeTime = Math.floor(\n      baseMediaDecodeTime % (UINT32_MAX + 1),\n    );\n    return MP4.box(\n      MP4.types.traf,\n      MP4.box(\n        MP4.types.tfhd,\n        new Uint8Array([\n          0x00, // version 0\n          0x00,\n          0x00,\n          0x00, // flags\n          id >> 24,\n          (id >> 16) & 0xff,\n          (id >> 8) & 0xff,\n          id & 0xff, // track_ID\n        ]),\n      ),\n      MP4.box(\n        MP4.types.tfdt,\n        new Uint8Array([\n          0x01, // version 1\n          0x00,\n          0x00,\n          0x00, // flags\n          upperWordBaseMediaDecodeTime >> 24,\n          (upperWordBaseMediaDecodeTime >> 16) & 0xff,\n          (upperWordBaseMediaDecodeTime >> 8) & 0xff,\n          upperWordBaseMediaDecodeTime & 0xff,\n          lowerWordBaseMediaDecodeTime >> 24,\n          (lowerWordBaseMediaDecodeTime >> 16) & 0xff,\n          (lowerWordBaseMediaDecodeTime >> 8) & 0xff,\n          lowerWordBaseMediaDecodeTime & 0xff,\n        ]),\n      ),\n      MP4.trun(\n        track,\n        sampleDependencyTable.length +\n          16 + // tfhd\n          20 + // tfdt\n          8 + // traf header\n          16 + // mfhd\n          8 + // moof header\n          8,\n      ), // mdat header\n      sampleDependencyTable,\n    );\n  }\n\n  /**\n   * Generate a track box.\n   * @param track a track definition\n   */\n  static trak(track) {\n    track.duration = track.duration || 0xffffffff;\n    return MP4.box(MP4.types.trak, MP4.tkhd(track), MP4.mdia(track));\n  }\n\n  static trex(track) {\n    const id = track.id;\n    return MP4.box(\n      MP4.types.trex,\n      new Uint8Array([\n        0x00, // version 0\n        0x00,\n        0x00,\n        0x00, // flags\n        id >> 24,\n        (id >> 16) & 0xff,\n        (id >> 8) & 0xff,\n        id & 0xff, // track_ID\n        0x00,\n        0x00,\n        0x00,\n        0x01, // default_sample_description_index\n        0x00,\n        0x00,\n        0x00,\n        0x00, // default_sample_duration\n        0x00,\n        0x00,\n        0x00,\n        0x00, // default_sample_size\n        0x00,\n        0x01,\n        0x00,\n        0x01, // default_sample_flags\n      ]),\n    );\n  }\n\n  static trun(track, offset) {\n    const samples = track.samples || [];\n    const len = samples.length;\n    const arraylen = 12 + 16 * len;\n    const array = new Uint8Array(arraylen);\n    let i;\n    let sample;\n    let duration;\n    let size;\n    let flags;\n    let cts;\n    offset += 8 + arraylen;\n    array.set(\n      [\n        track.type === 'video' ? 0x01 : 0x00, // version 1 for video with signed-int sample_composition_time_offset\n        0x00,\n        0x0f,\n        0x01, // flags\n        (len >>> 24) & 0xff,\n        (len >>> 16) & 0xff,\n        (len >>> 8) & 0xff,\n        len & 0xff, // sample_count\n        (offset >>> 24) & 0xff,\n        (offset >>> 16) & 0xff,\n        (offset >>> 8) & 0xff,\n        offset & 0xff, // data_offset\n      ],\n      0,\n    );\n    for (i = 0; i < len; i++) {\n      sample = samples[i];\n      duration = sample.duration;\n      size = sample.size;\n      flags = sample.flags;\n      cts = sample.cts;\n      array.set(\n        [\n          (duration >>> 24) & 0xff,\n          (duration >>> 16) & 0xff,\n          (duration >>> 8) & 0xff,\n          duration & 0xff, // sample_duration\n          (size >>> 24) & 0xff,\n          (size >>> 16) & 0xff,\n          (size >>> 8) & 0xff,\n          size & 0xff, // sample_size\n          (flags.isLeading << 2) | flags.dependsOn,\n          (flags.isDependedOn << 6) |\n            (flags.hasRedundancy << 4) |\n            (flags.paddingValue << 1) |\n            flags.isNonSync,\n          flags.degradPrio & (0xf0 << 8),\n          flags.degradPrio & 0x0f, // sample_flags\n          (cts >>> 24) & 0xff,\n          (cts >>> 16) & 0xff,\n          (cts >>> 8) & 0xff,\n          cts & 0xff, // sample_composition_time_offset\n        ],\n        12 + 16 * i,\n      );\n    }\n    return MP4.box(MP4.types.trun, array);\n  }\n\n  static initSegment(tracks) {\n    if (!MP4.types) {\n      MP4.init();\n    }\n\n    const movie = MP4.moov(tracks);\n    const result = appendUint8Array(MP4.FTYP, movie);\n    return result;\n  }\n}\n\nexport default MP4;\n", "const MPEG_TS_CLOCK_FREQ_HZ = 90000;\n\nexport type RationalTimestamp = {\n  baseTime: number; // ticks\n  timescale: number; // ticks per second\n};\n\nexport function toTimescaleFromBase(\n  baseTime: number,\n  destScale: number,\n  srcBase: number = 1,\n  round: boolean = false,\n): number {\n  const result = baseTime * destScale * srcBase; // equivalent to `(value * scale) / (1 / base)`\n  return round ? Math.round(result) : result;\n}\n\nexport function toTimescaleFromScale(\n  baseTime: number,\n  destScale: number,\n  srcScale: number = 1,\n  round: boolean = false,\n): number {\n  return toTimescaleFromBase(baseTime, destScale, 1 / srcScale, round);\n}\n\nexport function toMsFromMpegTsClock(\n  baseTime: number,\n  round: boolean = false,\n): number {\n  return toTimescaleFromBase(baseTime, 1000, 1 / MPEG_TS_CLOCK_FREQ_HZ, round);\n}\n\nexport function toMpegTsClockFromTimescale(\n  baseTime: number,\n  srcScale: number = 1,\n): number {\n  return toTimescaleFromBase(baseTime, MPEG_TS_CLOCK_FREQ_HZ, 1 / srcScale);\n}\n", "import AAC from './aac-helper';\nimport MP4 from './mp4-generator';\nimport type { HlsEventEmitter } from '../events';\nimport { Events } from '../events';\nimport { ErrorTypes, ErrorDetails } from '../errors';\nimport { logger } from '../utils/logger';\nimport {\n  InitSegmentData,\n  Remuxer,\n  RemuxerResult,\n  RemuxedMetadata,\n  RemuxedTrack,\n  RemuxedUserdata,\n} from '../types/remuxer';\nimport { PlaylistLevelType } from '../types/loader';\nimport {\n  RationalTimestamp,\n  toMsFromMpegTsClock,\n} from '../utils/timescale-conversion';\nimport type {\n  AudioSample,\n  VideoSample,\n  DemuxedAudioTrack,\n  DemuxedVideoTrack,\n  DemuxedMetadataTrack,\n  DemuxedUserdataTrack,\n} from '../types/demuxer';\nimport type { TrackSet } from '../types/track';\nimport type { SourceBufferName } from '../types/buffer';\nimport type { Fragment } from '../loader/fragment';\nimport type { HlsConfig } from '../config';\n\nconst MAX_SILENT_FRAME_DURATION = 10 * 1000; // 10 seconds\nconst AAC_SAMPLES_PER_FRAME = 1024;\nconst MPEG_AUDIO_SAMPLE_PER_FRAME = 1152;\nconst AC3_SAMPLES_PER_FRAME = 1536;\n\nlet chromeVersion: number | null = null;\nlet safariWebkitVersion: number | null = null;\n\nexport default class MP4Remuxer implements Remuxer {\n  private observer: HlsEventEmitter;\n  private config: HlsConfig;\n  private typeSupported: any;\n  private ISGenerated: boolean = false;\n  private _initPTS: RationalTimestamp | null = null;\n  private _initDTS: RationalTimestamp | null = null;\n  private nextAvcDts: number | null = null;\n  private nextAudioPts: number | null = null;\n  private videoSampleDuration: number | null = null;\n  private isAudioContiguous: boolean = false;\n  private isVideoContiguous: boolean = false;\n  private videoTrackConfig?: {\n    width?: number;\n    height?: number;\n    pixelRatio?: [number, number];\n  };\n\n  constructor(\n    observer: HlsEventEmitter,\n    config: HlsConfig,\n    typeSupported,\n    vendor = '',\n  ) {\n    this.observer = observer;\n    this.config = config;\n    this.typeSupported = typeSupported;\n    this.ISGenerated = false;\n\n    if (chromeVersion === null) {\n      const userAgent = navigator.userAgent || '';\n      const result = userAgent.match(/Chrome\\/(\\d+)/i);\n      chromeVersion = result ? parseInt(result[1]) : 0;\n    }\n    if (safariWebkitVersion === null) {\n      const result = navigator.userAgent.match(/Safari\\/(\\d+)/i);\n      safariWebkitVersion = result ? parseInt(result[1]) : 0;\n    }\n  }\n\n  destroy() {\n    // @ts-ignore\n    this.config = this.videoTrackConfig = this._initPTS = this._initDTS = null;\n  }\n\n  resetTimeStamp(defaultTimeStamp: RationalTimestamp | null) {\n    logger.log('[mp4-remuxer]: initPTS & initDTS reset');\n    this._initPTS = this._initDTS = defaultTimeStamp;\n  }\n\n  resetNextTimestamp() {\n    logger.log('[mp4-remuxer]: reset next timestamp');\n    this.isVideoContiguous = false;\n    this.isAudioContiguous = false;\n  }\n\n  resetInitSegment() {\n    logger.log('[mp4-remuxer]: ISGenerated flag reset');\n    this.ISGenerated = false;\n    this.videoTrackConfig = undefined;\n  }\n\n  getVideoStartPts(videoSamples) {\n    let rolloverDetected = false;\n    const startPTS = videoSamples.reduce((minPTS, sample) => {\n      const delta = sample.pts - minPTS;\n      if (delta < -4294967296) {\n        // 2^32, see PTSNormalize for reasoning, but we're hitting a rollover here, and we don't want that to impact the timeOffset calculation\n        rolloverDetected = true;\n        return normalizePts(minPTS, sample.pts);\n      } else if (delta > 0) {\n        return minPTS;\n      } else {\n        return sample.pts;\n      }\n    }, videoSamples[0].pts);\n    if (rolloverDetected) {\n      logger.debug('PTS rollover detected');\n    }\n    return startPTS;\n  }\n\n  remux(\n    audioTrack: DemuxedAudioTrack,\n    videoTrack: DemuxedVideoTrack,\n    id3Track: DemuxedMetadataTrack,\n    textTrack: DemuxedUserdataTrack,\n    timeOffset: number,\n    accurateTimeOffset: boolean,\n    flush: boolean,\n    playlistType: PlaylistLevelType,\n  ): RemuxerResult {\n    let video: RemuxedTrack | undefined;\n    let audio: RemuxedTrack | undefined;\n    let initSegment: InitSegmentData | undefined;\n    let text: RemuxedUserdata | undefined;\n    let id3: RemuxedMetadata | undefined;\n    let independent: boolean | undefined;\n    let audioTimeOffset = timeOffset;\n    let videoTimeOffset = timeOffset;\n\n    // If we're remuxing audio and video progressively, wait until we've received enough samples for each track before proceeding.\n    // This is done to synchronize the audio and video streams. We know if the current segment will have samples if the \"pid\"\n    // parameter is greater than -1. The pid is set when the PMT is parsed, which contains the tracks list.\n    // However, if the initSegment has already been generated, or we've reached the end of a segment (flush),\n    // then we can remux one track without waiting for the other.\n    const hasAudio = audioTrack.pid > -1;\n    const hasVideo = videoTrack.pid > -1;\n    const length = videoTrack.samples.length;\n    const enoughAudioSamples = audioTrack.samples.length > 0;\n    const enoughVideoSamples = (flush && length > 0) || length > 1;\n    const canRemuxAvc =\n      ((!hasAudio || enoughAudioSamples) &&\n        (!hasVideo || enoughVideoSamples)) ||\n      this.ISGenerated ||\n      flush;\n\n    if (canRemuxAvc) {\n      if (this.ISGenerated) {\n        const config = this.videoTrackConfig;\n        if (\n          config &&\n          (videoTrack.width !== config.width ||\n            videoTrack.height !== config.height ||\n            videoTrack.pixelRatio?.[0] !== config.pixelRatio?.[0] ||\n            videoTrack.pixelRatio?.[1] !== config.pixelRatio?.[1])\n        ) {\n          this.resetInitSegment();\n        }\n      } else {\n        initSegment = this.generateIS(\n          audioTrack,\n          videoTrack,\n          timeOffset,\n          accurateTimeOffset,\n        );\n      }\n\n      const isVideoContiguous = this.isVideoContiguous;\n      let firstKeyFrameIndex = -1;\n      let firstKeyFramePTS;\n\n      if (enoughVideoSamples) {\n        firstKeyFrameIndex = findKeyframeIndex(videoTrack.samples);\n        if (!isVideoContiguous && this.config.forceKeyFrameOnDiscontinuity) {\n          independent = true;\n          if (firstKeyFrameIndex > 0) {\n            logger.warn(\n              `[mp4-remuxer]: Dropped ${firstKeyFrameIndex} out of ${length} video samples due to a missing keyframe`,\n            );\n            const startPTS = this.getVideoStartPts(videoTrack.samples);\n            videoTrack.samples = videoTrack.samples.slice(firstKeyFrameIndex);\n            videoTrack.dropped += firstKeyFrameIndex;\n            videoTimeOffset +=\n              (videoTrack.samples[0].pts - startPTS) /\n              videoTrack.inputTimeScale;\n            firstKeyFramePTS = videoTimeOffset;\n          } else if (firstKeyFrameIndex === -1) {\n            logger.warn(\n              `[mp4-remuxer]: No keyframe found out of ${length} video samples`,\n            );\n            independent = false;\n          }\n        }\n      }\n\n      if (this.ISGenerated) {\n        if (enoughAudioSamples && enoughVideoSamples) {\n          // timeOffset is expected to be the offset of the first timestamp of this fragment (first DTS)\n          // if first audio DTS is not aligned with first video DTS then we need to take that into account\n          // when providing timeOffset to remuxAudio / remuxVideo. if we don't do that, there might be a permanent / small\n          // drift between audio and video streams\n          const startPTS = this.getVideoStartPts(videoTrack.samples);\n          const tsDelta =\n            normalizePts(audioTrack.samples[0].pts, startPTS) - startPTS;\n          const audiovideoTimestampDelta = tsDelta / videoTrack.inputTimeScale;\n          audioTimeOffset += Math.max(0, audiovideoTimestampDelta);\n          videoTimeOffset += Math.max(0, -audiovideoTimestampDelta);\n        }\n\n        // Purposefully remuxing audio before video, so that remuxVideo can use nextAudioPts, which is calculated in remuxAudio.\n        if (enoughAudioSamples) {\n          // if initSegment was generated without audio samples, regenerate it again\n          if (!audioTrack.samplerate) {\n            logger.warn(\n              '[mp4-remuxer]: regenerate InitSegment as audio detected',\n            );\n            initSegment = this.generateIS(\n              audioTrack,\n              videoTrack,\n              timeOffset,\n              accurateTimeOffset,\n            );\n          }\n          audio = this.remuxAudio(\n            audioTrack,\n            audioTimeOffset,\n            this.isAudioContiguous,\n            accurateTimeOffset,\n            hasVideo ||\n              enoughVideoSamples ||\n              playlistType === PlaylistLevelType.AUDIO\n              ? videoTimeOffset\n              : undefined,\n          );\n          if (enoughVideoSamples) {\n            const audioTrackLength = audio ? audio.endPTS - audio.startPTS : 0;\n            // if initSegment was generated without video samples, regenerate it again\n            if (!videoTrack.inputTimeScale) {\n              logger.warn(\n                '[mp4-remuxer]: regenerate InitSegment as video detected',\n              );\n              initSegment = this.generateIS(\n                audioTrack,\n                videoTrack,\n                timeOffset,\n                accurateTimeOffset,\n              );\n            }\n            video = this.remuxVideo(\n              videoTrack,\n              videoTimeOffset,\n              isVideoContiguous,\n              audioTrackLength,\n            );\n          }\n        } else if (enoughVideoSamples) {\n          video = this.remuxVideo(\n            videoTrack,\n            videoTimeOffset,\n            isVideoContiguous,\n            0,\n          );\n        }\n        if (video) {\n          video.firstKeyFrame = firstKeyFrameIndex;\n          video.independent = firstKeyFrameIndex !== -1;\n          video.firstKeyFramePTS = firstKeyFramePTS;\n        }\n      }\n    }\n\n    // Allow ID3 and text to remux, even if more audio/video samples are required\n    if (this.ISGenerated && this._initPTS && this._initDTS) {\n      if (id3Track.samples.length) {\n        id3 = flushTextTrackMetadataCueSamples(\n          id3Track,\n          timeOffset,\n          this._initPTS,\n          this._initDTS,\n        );\n      }\n\n      if (textTrack.samples.length) {\n        text = flushTextTrackUserdataCueSamples(\n          textTrack,\n          timeOffset,\n          this._initPTS,\n        );\n      }\n    }\n\n    return {\n      audio,\n      video,\n      initSegment,\n      independent,\n      text,\n      id3,\n    };\n  }\n\n  generateIS(\n    audioTrack: DemuxedAudioTrack,\n    videoTrack: DemuxedVideoTrack,\n    timeOffset: number,\n    accurateTimeOffset: boolean,\n  ): InitSegmentData | undefined {\n    const audioSamples = audioTrack.samples;\n    const videoSamples = videoTrack.samples;\n    const typeSupported = this.typeSupported;\n    const tracks: TrackSet = {};\n    const _initPTS = this._initPTS;\n    let computePTSDTS = !_initPTS || accurateTimeOffset;\n    let container = 'audio/mp4';\n    let initPTS: number | undefined;\n    let initDTS: number | undefined;\n    let timescale: number | undefined;\n\n    if (computePTSDTS) {\n      initPTS = initDTS = Infinity;\n    }\n\n    if (audioTrack.config && audioSamples.length) {\n      // let's use audio sampling rate as MP4 time scale.\n      // rationale is that there is a integer nb of audio frames per audio sample (1024 for AAC)\n      // using audio sampling rate here helps having an integer MP4 frame duration\n      // this avoids potential rounding issue and AV sync issue\n      audioTrack.timescale = audioTrack.samplerate;\n      switch (audioTrack.segmentCodec) {\n        case 'mp3':\n          if (typeSupported.mpeg) {\n            // Chrome and Safari\n            container = 'audio/mpeg';\n            audioTrack.codec = '';\n          } else if (typeSupported.mp3) {\n            // Firefox\n            audioTrack.codec = 'mp3';\n          }\n          break;\n\n        case 'ac3':\n          audioTrack.codec = 'ac-3';\n          break;\n      }\n      tracks.audio = {\n        id: 'audio',\n        container: container,\n        codec: audioTrack.codec,\n        initSegment:\n          audioTrack.segmentCodec === 'mp3' && typeSupported.mpeg\n            ? new Uint8Array(0)\n            : MP4.initSegment([audioTrack]),\n        metadata: {\n          channelCount: audioTrack.channelCount,\n        },\n      };\n      if (computePTSDTS) {\n        timescale = audioTrack.inputTimeScale;\n        if (!_initPTS || timescale !== _initPTS.timescale) {\n          // remember first PTS of this demuxing context. for audio, PTS = DTS\n          initPTS = initDTS =\n            audioSamples[0].pts - Math.round(timescale * timeOffset);\n        } else {\n          computePTSDTS = false;\n        }\n      }\n    }\n\n    if (videoTrack.sps && videoTrack.pps && videoSamples.length) {\n      // let's use input time scale as MP4 video timescale\n      // we use input time scale straight away to avoid rounding issues on frame duration / cts computation\n      videoTrack.timescale = videoTrack.inputTimeScale;\n      tracks.video = {\n        id: 'main',\n        container: 'video/mp4',\n        codec: videoTrack.codec,\n        initSegment: MP4.initSegment([videoTrack]),\n        metadata: {\n          width: videoTrack.width,\n          height: videoTrack.height,\n        },\n      };\n      if (computePTSDTS) {\n        timescale = videoTrack.inputTimeScale;\n        if (!_initPTS || timescale !== _initPTS.timescale) {\n          const startPTS = this.getVideoStartPts(videoSamples);\n          const startOffset = Math.round(timescale * timeOffset);\n          initDTS = Math.min(\n            initDTS as number,\n            normalizePts(videoSamples[0].dts, startPTS) - startOffset,\n          );\n          initPTS = Math.min(initPTS as number, startPTS - startOffset);\n        } else {\n          computePTSDTS = false;\n        }\n      }\n      this.videoTrackConfig = {\n        width: videoTrack.width,\n        height: videoTrack.height,\n        pixelRatio: videoTrack.pixelRatio,\n      };\n    }\n\n    if (Object.keys(tracks).length) {\n      this.ISGenerated = true;\n      if (computePTSDTS) {\n        this._initPTS = {\n          baseTime: initPTS as number,\n          timescale: timescale as number,\n        };\n        this._initDTS = {\n          baseTime: initDTS as number,\n          timescale: timescale as number,\n        };\n      } else {\n        initPTS = timescale = undefined;\n      }\n\n      return {\n        tracks,\n        initPTS,\n        timescale,\n      };\n    }\n  }\n\n  remuxVideo(\n    track: DemuxedVideoTrack,\n    timeOffset: number,\n    contiguous: boolean,\n    audioTrackLength: number,\n  ): RemuxedTrack | undefined {\n    const timeScale: number = track.inputTimeScale;\n    const inputSamples: Array<VideoSample> = track.samples;\n    const outputSamples: Array<Mp4Sample> = [];\n    const nbSamples = inputSamples.length;\n    const initPTS = this._initPTS as RationalTimestamp;\n    let nextAvcDts = this.nextAvcDts;\n    let offset = 8;\n    let mp4SampleDuration = this.videoSampleDuration;\n    let firstDTS;\n    let lastDTS;\n    let minPTS: number = Number.POSITIVE_INFINITY;\n    let maxPTS: number = Number.NEGATIVE_INFINITY;\n    let sortSamples = false;\n\n    // if parsed fragment is contiguous with last one, let's use last DTS value as reference\n    if (!contiguous || nextAvcDts === null) {\n      const pts = timeOffset * timeScale;\n      const cts =\n        inputSamples[0].pts -\n        normalizePts(inputSamples[0].dts, inputSamples[0].pts);\n      if (\n        chromeVersion &&\n        nextAvcDts !== null &&\n        Math.abs(pts - cts - nextAvcDts) < 15000\n      ) {\n        // treat as contigous to adjust samples that would otherwise produce video buffer gaps in Chrome\n        contiguous = true;\n      } else {\n        // if not contiguous, let's use target timeOffset\n        nextAvcDts = pts - cts;\n      }\n    }\n\n    // PTS is coded on 33bits, and can loop from -2^32 to 2^32\n    // PTSNormalize will make PTS/DTS value monotonic, we use last known DTS value as reference value\n    const initTime = (initPTS.baseTime * timeScale) / initPTS.timescale;\n    for (let i = 0; i < nbSamples; i++) {\n      const sample = inputSamples[i];\n      sample.pts = normalizePts(sample.pts - initTime, nextAvcDts);\n      sample.dts = normalizePts(sample.dts - initTime, nextAvcDts);\n      if (sample.dts < inputSamples[i > 0 ? i - 1 : i].dts) {\n        sortSamples = true;\n      }\n    }\n\n    // sort video samples by DTS then PTS then demux id order\n    if (sortSamples) {\n      inputSamples.sort(function (a, b) {\n        const deltadts = a.dts - b.dts;\n        const deltapts = a.pts - b.pts;\n        return deltadts || deltapts;\n      });\n    }\n\n    // Get first/last DTS\n    firstDTS = inputSamples[0].dts;\n    lastDTS = inputSamples[inputSamples.length - 1].dts;\n\n    // Sample duration (as expected by trun MP4 boxes), should be the delta between sample DTS\n    // set this constant duration as being the avg delta between consecutive DTS.\n    const inputDuration = lastDTS - firstDTS;\n    const averageSampleDuration = inputDuration\n      ? Math.round(inputDuration / (nbSamples - 1))\n      : mp4SampleDuration || track.inputTimeScale / 30;\n\n    // if fragment are contiguous, detect hole/overlapping between fragments\n    if (contiguous) {\n      // check timestamp continuity across consecutive fragments (this is to remove inter-fragment gap/hole)\n      const delta = firstDTS - nextAvcDts;\n      const foundHole = delta > averageSampleDuration;\n      const foundOverlap = delta < -1;\n      if (foundHole || foundOverlap) {\n        if (foundHole) {\n          logger.warn(\n            `AVC: ${toMsFromMpegTsClock(\n              delta,\n              true,\n            )} ms (${delta}dts) hole between fragments detected at ${timeOffset.toFixed(\n              3,\n            )}`,\n          );\n        } else {\n          logger.warn(\n            `AVC: ${toMsFromMpegTsClock(\n              -delta,\n              true,\n            )} ms (${delta}dts) overlapping between fragments detected at ${timeOffset.toFixed(\n              3,\n            )}`,\n          );\n        }\n        if (\n          !foundOverlap ||\n          nextAvcDts >= inputSamples[0].pts ||\n          chromeVersion\n        ) {\n          firstDTS = nextAvcDts;\n          const firstPTS = inputSamples[0].pts - delta;\n          if (foundHole) {\n            inputSamples[0].dts = firstDTS;\n            inputSamples[0].pts = firstPTS;\n          } else {\n            for (let i = 0; i < inputSamples.length; i++) {\n              if (inputSamples[i].dts > firstPTS) {\n                break;\n              }\n              inputSamples[i].dts -= delta;\n              inputSamples[i].pts -= delta;\n            }\n          }\n          logger.log(\n            `Video: Initial PTS/DTS adjusted: ${toMsFromMpegTsClock(\n              firstPTS,\n              true,\n            )}/${toMsFromMpegTsClock(\n              firstDTS,\n              true,\n            )}, delta: ${toMsFromMpegTsClock(delta, true)} ms`,\n          );\n        }\n      }\n    }\n\n    firstDTS = Math.max(0, firstDTS);\n\n    let nbNalu = 0;\n    let naluLen = 0;\n    let dtsStep = firstDTS;\n    for (let i = 0; i < nbSamples; i++) {\n      // compute total/avc sample length and nb of NAL units\n      const sample = inputSamples[i];\n      const units = sample.units;\n      const nbUnits = units.length;\n      let sampleLen = 0;\n      for (let j = 0; j < nbUnits; j++) {\n        sampleLen += units[j].data.length;\n      }\n\n      naluLen += sampleLen;\n      nbNalu += nbUnits;\n      sample.length = sampleLen;\n\n      // ensure sample monotonic DTS\n      if (sample.dts < dtsStep) {\n        sample.dts = dtsStep;\n        dtsStep += (averageSampleDuration / 4) | 0 || 1;\n      } else {\n        dtsStep = sample.dts;\n      }\n\n      minPTS = Math.min(sample.pts, minPTS);\n      maxPTS = Math.max(sample.pts, maxPTS);\n    }\n    lastDTS = inputSamples[nbSamples - 1].dts;\n\n    /* concatenate the video data and construct the mdat in place\n      (need 8 more bytes to fill length and mpdat type) */\n    const mdatSize = naluLen + 4 * nbNalu + 8;\n    let mdat;\n    try {\n      mdat = new Uint8Array(mdatSize);\n    } catch (err) {\n      this.observer.emit(Events.ERROR, Events.ERROR, {\n        type: ErrorTypes.MUX_ERROR,\n        details: ErrorDetails.REMUX_ALLOC_ERROR,\n        fatal: false,\n        error: err,\n        bytes: mdatSize,\n        reason: `fail allocating video mdat ${mdatSize}`,\n      });\n      return;\n    }\n    const view = new DataView(mdat.buffer);\n    view.setUint32(0, mdatSize);\n    mdat.set(MP4.types.mdat, 4);\n\n    let stretchedLastFrame = false;\n    let minDtsDelta = Number.POSITIVE_INFINITY;\n    let minPtsDelta = Number.POSITIVE_INFINITY;\n    let maxDtsDelta = Number.NEGATIVE_INFINITY;\n    let maxPtsDelta = Number.NEGATIVE_INFINITY;\n    for (let i = 0; i < nbSamples; i++) {\n      const VideoSample = inputSamples[i];\n      const VideoSampleUnits = VideoSample.units;\n      let mp4SampleLength = 0;\n      // convert NALU bitstream to MP4 format (prepend NALU with size field)\n      for (let j = 0, nbUnits = VideoSampleUnits.length; j < nbUnits; j++) {\n        const unit = VideoSampleUnits[j];\n        const unitData = unit.data;\n        const unitDataLen = unit.data.byteLength;\n        view.setUint32(offset, unitDataLen);\n        offset += 4;\n        mdat.set(unitData, offset);\n        offset += unitDataLen;\n        mp4SampleLength += 4 + unitDataLen;\n      }\n\n      // expected sample duration is the Decoding Timestamp diff of consecutive samples\n      let ptsDelta;\n      if (i < nbSamples - 1) {\n        mp4SampleDuration = inputSamples[i + 1].dts - VideoSample.dts;\n        ptsDelta = inputSamples[i + 1].pts - VideoSample.pts;\n      } else {\n        const config = this.config;\n        const lastFrameDuration =\n          i > 0\n            ? VideoSample.dts - inputSamples[i - 1].dts\n            : averageSampleDuration;\n        ptsDelta =\n          i > 0\n            ? VideoSample.pts - inputSamples[i - 1].pts\n            : averageSampleDuration;\n        if (config.stretchShortVideoTrack && this.nextAudioPts !== null) {\n          // In some cases, a segment's audio track duration may exceed the video track duration.\n          // Since we've already remuxed audio, and we know how long the audio track is, we look to\n          // see if the delta to the next segment is longer than maxBufferHole.\n          // If so, playback would potentially get stuck, so we artificially inflate\n          // the duration of the last frame to minimize any potential gap between segments.\n          const gapTolerance = Math.floor(config.maxBufferHole * timeScale);\n          const deltaToFrameEnd =\n            (audioTrackLength\n              ? minPTS + audioTrackLength * timeScale\n              : this.nextAudioPts) - VideoSample.pts;\n          if (deltaToFrameEnd > gapTolerance) {\n            // We subtract lastFrameDuration from deltaToFrameEnd to try to prevent any video\n            // frame overlap. maxBufferHole should be >> lastFrameDuration anyway.\n            mp4SampleDuration = deltaToFrameEnd - lastFrameDuration;\n            if (mp4SampleDuration < 0) {\n              mp4SampleDuration = lastFrameDuration;\n            } else {\n              stretchedLastFrame = true;\n            }\n            logger.log(\n              `[mp4-remuxer]: It is approximately ${\n                deltaToFrameEnd / 90\n              } ms to the next segment; using duration ${\n                mp4SampleDuration / 90\n              } ms for the last video frame.`,\n            );\n          } else {\n            mp4SampleDuration = lastFrameDuration;\n          }\n        } else {\n          mp4SampleDuration = lastFrameDuration;\n        }\n      }\n      const compositionTimeOffset = Math.round(\n        VideoSample.pts - VideoSample.dts,\n      );\n      minDtsDelta = Math.min(minDtsDelta, mp4SampleDuration);\n      maxDtsDelta = Math.max(maxDtsDelta, mp4SampleDuration);\n      minPtsDelta = Math.min(minPtsDelta, ptsDelta);\n      maxPtsDelta = Math.max(maxPtsDelta, ptsDelta);\n\n      outputSamples.push(\n        new Mp4Sample(\n          VideoSample.key,\n          mp4SampleDuration,\n          mp4SampleLength,\n          compositionTimeOffset,\n        ),\n      );\n    }\n\n    if (outputSamples.length) {\n      if (chromeVersion) {\n        if (chromeVersion < 70) {\n          // Chrome workaround, mark first sample as being a Random Access Point (keyframe) to avoid sourcebuffer append issue\n          // https://code.google.com/p/chromium/issues/detail?id=229412\n          const flags = outputSamples[0].flags;\n          flags.dependsOn = 2;\n          flags.isNonSync = 0;\n        }\n      } else if (safariWebkitVersion) {\n        // Fix for \"CNN special report, with CC\" in test-streams (Safari browser only)\n        // Ignore DTS when frame durations are irregular. Safari MSE does not handle this leading to gaps.\n        if (\n          maxPtsDelta - minPtsDelta < maxDtsDelta - minDtsDelta &&\n          averageSampleDuration / maxDtsDelta < 0.025 &&\n          outputSamples[0].cts === 0\n        ) {\n          logger.warn(\n            'Found irregular gaps in sample duration. Using PTS instead of DTS to determine MP4 sample duration.',\n          );\n          let dts = firstDTS;\n          for (let i = 0, len = outputSamples.length; i < len; i++) {\n            const nextDts = dts + outputSamples[i].duration;\n            const pts = dts + outputSamples[i].cts;\n            if (i < len - 1) {\n              const nextPts = nextDts + outputSamples[i + 1].cts;\n              outputSamples[i].duration = nextPts - pts;\n            } else {\n              outputSamples[i].duration = i\n                ? outputSamples[i - 1].duration\n                : averageSampleDuration;\n            }\n            outputSamples[i].cts = 0;\n            dts = nextDts;\n          }\n        }\n      }\n    }\n    // next AVC sample DTS should be equal to last sample DTS + last sample duration (in PES timescale)\n    mp4SampleDuration =\n      stretchedLastFrame || !mp4SampleDuration\n        ? averageSampleDuration\n        : mp4SampleDuration;\n    this.nextAvcDts = nextAvcDts = lastDTS + mp4SampleDuration;\n    this.videoSampleDuration = mp4SampleDuration;\n    this.isVideoContiguous = true;\n    const moof = MP4.moof(\n      track.sequenceNumber++,\n      firstDTS,\n      Object.assign({}, track, {\n        samples: outputSamples,\n      }),\n    );\n    const type: SourceBufferName = 'video';\n    const data = {\n      data1: moof,\n      data2: mdat,\n      startPTS: minPTS / timeScale,\n      endPTS: (maxPTS + mp4SampleDuration) / timeScale,\n      startDTS: firstDTS / timeScale,\n      endDTS: (nextAvcDts as number) / timeScale,\n      type,\n      hasAudio: false,\n      hasVideo: true,\n      nb: outputSamples.length,\n      dropped: track.dropped,\n    };\n    track.samples = [];\n    track.dropped = 0;\n    return data;\n  }\n\n  getSamplesPerFrame(track: DemuxedAudioTrack) {\n    switch (track.segmentCodec) {\n      case 'mp3':\n        return MPEG_AUDIO_SAMPLE_PER_FRAME;\n      case 'ac3':\n        return AC3_SAMPLES_PER_FRAME;\n      default:\n        return AAC_SAMPLES_PER_FRAME;\n    }\n  }\n\n  remuxAudio(\n    track: DemuxedAudioTrack,\n    timeOffset: number,\n    contiguous: boolean,\n    accurateTimeOffset: boolean,\n    videoTimeOffset?: number,\n  ): RemuxedTrack | undefined {\n    const inputTimeScale: number = track.inputTimeScale;\n    const mp4timeScale: number = track.samplerate\n      ? track.samplerate\n      : inputTimeScale;\n    const scaleFactor: number = inputTimeScale / mp4timeScale;\n    const mp4SampleDuration: number = this.getSamplesPerFrame(track);\n    const inputSampleDuration: number = mp4SampleDuration * scaleFactor;\n    const initPTS = this._initPTS as RationalTimestamp;\n    const rawMPEG: boolean =\n      track.segmentCodec === 'mp3' && this.typeSupported.mpeg;\n    const outputSamples: Array<Mp4Sample> = [];\n    const alignedWithVideo = videoTimeOffset !== undefined;\n\n    let inputSamples: Array<AudioSample> = track.samples;\n    let offset: number = rawMPEG ? 0 : 8;\n    let nextAudioPts: number = this.nextAudioPts || -1;\n\n    // window.audioSamples ? window.audioSamples.push(inputSamples.map(s => s.pts)) : (window.audioSamples = [inputSamples.map(s => s.pts)]);\n\n    // for audio samples, also consider consecutive fragments as being contiguous (even if a level switch occurs),\n    // for sake of clarity:\n    // consecutive fragments are frags with\n    //  - less than 100ms gaps between new time offset (if accurate) and next expected PTS OR\n    //  - less than 20 audio frames distance\n    // contiguous fragments are consecutive fragments from same quality level (same level, new SN = old SN + 1)\n    // this helps ensuring audio continuity\n    // and this also avoids audio glitches/cut when switching quality, or reporting wrong duration on first audio frame\n    const timeOffsetMpegTS = timeOffset * inputTimeScale;\n    const initTime = (initPTS.baseTime * inputTimeScale) / initPTS.timescale;\n    this.isAudioContiguous = contiguous =\n      contiguous ||\n      ((inputSamples.length &&\n        nextAudioPts > 0 &&\n        ((accurateTimeOffset &&\n          Math.abs(timeOffsetMpegTS - nextAudioPts) < 9000) ||\n          Math.abs(\n            normalizePts(inputSamples[0].pts - initTime, timeOffsetMpegTS) -\n              nextAudioPts,\n          ) <\n            20 * inputSampleDuration)) as boolean);\n\n    // compute normalized PTS\n    inputSamples.forEach(function (sample) {\n      sample.pts = normalizePts(sample.pts - initTime, timeOffsetMpegTS);\n    });\n\n    if (!contiguous || nextAudioPts < 0) {\n      // filter out sample with negative PTS that are not playable anyway\n      // if we don't remove these negative samples, they will shift all audio samples forward.\n      // leading to audio overlap between current / next fragment\n      inputSamples = inputSamples.filter((sample) => sample.pts >= 0);\n\n      // in case all samples have negative PTS, and have been filtered out, return now\n      if (!inputSamples.length) {\n        return;\n      }\n\n      if (videoTimeOffset === 0) {\n        // Set the start to 0 to match video so that start gaps larger than inputSampleDuration are filled with silence\n        nextAudioPts = 0;\n      } else if (accurateTimeOffset && !alignedWithVideo) {\n        // When not seeking, not live, and LevelDetails.PTSKnown, use fragment start as predicted next audio PTS\n        nextAudioPts = Math.max(0, timeOffsetMpegTS);\n      } else {\n        // if frags are not contiguous and if we cant trust time offset, let's use first sample PTS as next audio PTS\n        nextAudioPts = inputSamples[0].pts;\n      }\n    }\n\n    // If the audio track is missing samples, the frames seem to get \"left-shifted\" within the\n    // resulting mp4 segment, causing sync issues and leaving gaps at the end of the audio segment.\n    // In an effort to prevent this from happening, we inject frames here where there are gaps.\n    // When possible, we inject a silent frame; when that's not possible, we duplicate the last\n    // frame.\n\n    if (track.segmentCodec === 'aac') {\n      const maxAudioFramesDrift = this.config.maxAudioFramesDrift;\n      for (let i = 0, nextPts = nextAudioPts; i < inputSamples.length; i++) {\n        // First, let's see how far off this frame is from where we expect it to be\n        const sample = inputSamples[i];\n        const pts = sample.pts;\n        const delta = pts - nextPts;\n        const duration = Math.abs((1000 * delta) / inputTimeScale);\n\n        // When remuxing with video, if we're overlapping by more than a duration, drop this sample to stay in sync\n        if (\n          delta <= -maxAudioFramesDrift * inputSampleDuration &&\n          alignedWithVideo\n        ) {\n          if (i === 0) {\n            logger.warn(\n              `Audio frame @ ${(pts / inputTimeScale).toFixed(\n                3,\n              )}s overlaps nextAudioPts by ${Math.round(\n                (1000 * delta) / inputTimeScale,\n              )} ms.`,\n            );\n            this.nextAudioPts = nextAudioPts = nextPts = pts;\n          }\n        } // eslint-disable-line brace-style\n\n        // Insert missing frames if:\n        // 1: We're more than maxAudioFramesDrift frame away\n        // 2: Not more than MAX_SILENT_FRAME_DURATION away\n        // 3: currentTime (aka nextPtsNorm) is not 0\n        // 4: remuxing with video (videoTimeOffset !== undefined)\n        else if (\n          delta >= maxAudioFramesDrift * inputSampleDuration &&\n          duration < MAX_SILENT_FRAME_DURATION &&\n          alignedWithVideo\n        ) {\n          let missing = Math.round(delta / inputSampleDuration);\n          // Adjust nextPts so that silent samples are aligned with media pts. This will prevent media samples from\n          // later being shifted if nextPts is based on timeOffset and delta is not a multiple of inputSampleDuration.\n          nextPts = pts - missing * inputSampleDuration;\n          if (nextPts < 0) {\n            missing--;\n            nextPts += inputSampleDuration;\n          }\n          if (i === 0) {\n            this.nextAudioPts = nextAudioPts = nextPts;\n          }\n          logger.warn(\n            `[mp4-remuxer]: Injecting ${missing} audio frame @ ${(\n              nextPts / inputTimeScale\n            ).toFixed(3)}s due to ${Math.round(\n              (1000 * delta) / inputTimeScale,\n            )} ms gap.`,\n          );\n          for (let j = 0; j < missing; j++) {\n            const newStamp = Math.max(nextPts as number, 0);\n            let fillFrame = AAC.getSilentFrame(\n              track.manifestCodec || track.codec,\n              track.channelCount,\n            );\n            if (!fillFrame) {\n              logger.log(\n                '[mp4-remuxer]: Unable to get silent frame for given audio codec; duplicating last frame instead.',\n              );\n              fillFrame = sample.unit.subarray();\n            }\n            inputSamples.splice(i, 0, {\n              unit: fillFrame,\n              pts: newStamp,\n            });\n            nextPts += inputSampleDuration;\n            i++;\n          }\n        }\n        sample.pts = nextPts;\n        nextPts += inputSampleDuration;\n      }\n    }\n    let firstPTS: number | null = null;\n    let lastPTS: number | null = null;\n    let mdat: any;\n    let mdatSize: number = 0;\n    let sampleLength: number = inputSamples.length;\n    while (sampleLength--) {\n      mdatSize += inputSamples[sampleLength].unit.byteLength;\n    }\n    for (let j = 0, nbSamples = inputSamples.length; j < nbSamples; j++) {\n      const audioSample = inputSamples[j];\n      const unit = audioSample.unit;\n      let pts = audioSample.pts;\n      if (lastPTS !== null) {\n        // If we have more than one sample, set the duration of the sample to the \"real\" duration; the PTS diff with\n        // the previous sample\n        const prevSample = outputSamples[j - 1];\n        prevSample.duration = Math.round((pts - lastPTS) / scaleFactor);\n      } else {\n        if (contiguous && track.segmentCodec === 'aac') {\n          // set PTS/DTS to expected PTS/DTS\n          pts = nextAudioPts;\n        }\n        // remember first PTS of our audioSamples\n        firstPTS = pts;\n        if (mdatSize > 0) {\n          /* concatenate the audio data and construct the mdat in place\n            (need 8 more bytes to fill length and mdat type) */\n          mdatSize += offset;\n          try {\n            mdat = new Uint8Array(mdatSize);\n          } catch (err) {\n            this.observer.emit(Events.ERROR, Events.ERROR, {\n              type: ErrorTypes.MUX_ERROR,\n              details: ErrorDetails.REMUX_ALLOC_ERROR,\n              fatal: false,\n              error: err,\n              bytes: mdatSize,\n              reason: `fail allocating audio mdat ${mdatSize}`,\n            });\n            return;\n          }\n          if (!rawMPEG) {\n            const view = new DataView(mdat.buffer);\n            view.setUint32(0, mdatSize);\n            mdat.set(MP4.types.mdat, 4);\n          }\n        } else {\n          // no audio samples\n          return;\n        }\n      }\n      mdat.set(unit, offset);\n      const unitLen = unit.byteLength;\n      offset += unitLen;\n      // Default the sample's duration to the computed mp4SampleDuration, which will either be 1024 for AAC or 1152 for MPEG\n      // In the case that we have 1 sample, this will be the duration. If we have more than one sample, the duration\n      // becomes the PTS diff with the previous sample\n      outputSamples.push(new Mp4Sample(true, mp4SampleDuration, unitLen, 0));\n      lastPTS = pts;\n    }\n\n    // We could end up with no audio samples if all input samples were overlapping with the previously remuxed ones\n    const nbSamples = outputSamples.length;\n    if (!nbSamples) {\n      return;\n    }\n\n    // The next audio sample PTS should be equal to last sample PTS + duration\n    const lastSample = outputSamples[outputSamples.length - 1];\n    this.nextAudioPts = nextAudioPts =\n      lastPTS! + scaleFactor * lastSample.duration;\n\n    // Set the track samples from inputSamples to outputSamples before remuxing\n    const moof = rawMPEG\n      ? new Uint8Array(0)\n      : MP4.moof(\n          track.sequenceNumber++,\n          firstPTS! / scaleFactor,\n          Object.assign({}, track, { samples: outputSamples }),\n        );\n\n    // Clear the track samples. This also clears the samples array in the demuxer, since the reference is shared\n    track.samples = [];\n    const start = firstPTS! / inputTimeScale;\n    const end = nextAudioPts / inputTimeScale;\n    const type: SourceBufferName = 'audio';\n    const audioData = {\n      data1: moof,\n      data2: mdat,\n      startPTS: start,\n      endPTS: end,\n      startDTS: start,\n      endDTS: end,\n      type,\n      hasAudio: true,\n      hasVideo: false,\n      nb: nbSamples,\n    };\n\n    this.isAudioContiguous = true;\n    return audioData;\n  }\n\n  remuxEmptyAudio(\n    track: DemuxedAudioTrack,\n    timeOffset: number,\n    contiguous: boolean,\n    videoData: Fragment,\n  ): RemuxedTrack | undefined {\n    const inputTimeScale: number = track.inputTimeScale;\n    const mp4timeScale: number = track.samplerate\n      ? track.samplerate\n      : inputTimeScale;\n    const scaleFactor: number = inputTimeScale / mp4timeScale;\n    const nextAudioPts: number | null = this.nextAudioPts;\n    // sync with video's timestamp\n    const initDTS = this._initDTS as RationalTimestamp;\n    const init90kHz = (initDTS.baseTime * 90000) / initDTS.timescale;\n    const startDTS: number =\n      (nextAudioPts !== null\n        ? nextAudioPts\n        : videoData.startDTS * inputTimeScale) + init90kHz;\n    const endDTS: number = videoData.endDTS * inputTimeScale + init90kHz;\n    // one sample's duration value\n    const frameDuration: number = scaleFactor * AAC_SAMPLES_PER_FRAME;\n    // samples count of this segment's duration\n    const nbSamples: number = Math.ceil((endDTS - startDTS) / frameDuration);\n    // silent frame\n    const silentFrame: Uint8Array | undefined = AAC.getSilentFrame(\n      track.manifestCodec || track.codec,\n      track.channelCount,\n    );\n\n    logger.warn('[mp4-remuxer]: remux empty Audio');\n    // Can't remux if we can't generate a silent frame...\n    if (!silentFrame) {\n      logger.trace(\n        '[mp4-remuxer]: Unable to remuxEmptyAudio since we were unable to get a silent frame for given audio codec',\n      );\n      return;\n    }\n\n    const samples: Array<any> = [];\n    for (let i = 0; i < nbSamples; i++) {\n      const stamp = startDTS + i * frameDuration;\n      samples.push({ unit: silentFrame, pts: stamp, dts: stamp });\n    }\n    track.samples = samples;\n\n    return this.remuxAudio(track, timeOffset, contiguous, false);\n  }\n}\n\nexport function normalizePts(value: number, reference: number | null): number {\n  let offset;\n  if (reference === null) {\n    return value;\n  }\n\n  if (reference < value) {\n    // - 2^33\n    offset = -8589934592;\n  } else {\n    // + 2^33\n    offset = 8589934592;\n  }\n  /* PTS is 33bit (from 0 to 2^33 -1)\n    if diff between value and reference is bigger than half of the amplitude (2^32) then it means that\n    PTS looping occured. fill the gap */\n  while (Math.abs(value - reference) > 4294967296) {\n    value += offset;\n  }\n\n  return value;\n}\n\nfunction findKeyframeIndex(samples: Array<VideoSample>): number {\n  for (let i = 0; i < samples.length; i++) {\n    if (samples[i].key) {\n      return i;\n    }\n  }\n  return -1;\n}\n\nexport function flushTextTrackMetadataCueSamples(\n  track: DemuxedMetadataTrack,\n  timeOffset: number,\n  initPTS: RationalTimestamp,\n  initDTS: RationalTimestamp,\n): RemuxedMetadata | undefined {\n  const length = track.samples.length;\n  if (!length) {\n    return;\n  }\n  const inputTimeScale = track.inputTimeScale;\n  for (let index = 0; index < length; index++) {\n    const sample = track.samples[index];\n    // setting id3 pts, dts to relative time\n    // using this._initPTS and this._initDTS to calculate relative time\n    sample.pts =\n      normalizePts(\n        sample.pts - (initPTS.baseTime * inputTimeScale) / initPTS.timescale,\n        timeOffset * inputTimeScale,\n      ) / inputTimeScale;\n    sample.dts =\n      normalizePts(\n        sample.dts - (initDTS.baseTime * inputTimeScale) / initDTS.timescale,\n        timeOffset * inputTimeScale,\n      ) / inputTimeScale;\n  }\n  const samples = track.samples;\n  track.samples = [];\n  return {\n    samples,\n  };\n}\n\nexport function flushTextTrackUserdataCueSamples(\n  track: DemuxedUserdataTrack,\n  timeOffset: number,\n  initPTS: RationalTimestamp,\n): RemuxedUserdata | undefined {\n  const length = track.samples.length;\n  if (!length) {\n    return;\n  }\n\n  const inputTimeScale = track.inputTimeScale;\n  for (let index = 0; index < length; index++) {\n    const sample = track.samples[index];\n    // setting text pts, dts to relative time\n    // using this._initPTS and this._initDTS to calculate relative time\n    sample.pts =\n      normalizePts(\n        sample.pts - (initPTS.baseTime * inputTimeScale) / initPTS.timescale,\n        timeOffset * inputTimeScale,\n      ) / inputTimeScale;\n  }\n  track.samples.sort((a, b) => a.pts - b.pts);\n  const samples = track.samples;\n  track.samples = [];\n  return {\n    samples,\n  };\n}\n\ntype Mp4SampleFlags = {\n  isLeading: 0;\n  isDependedOn: 0;\n  hasRedundancy: 0;\n  degradPrio: 0;\n  dependsOn: 1 | 2;\n  isNonSync: 0 | 1;\n};\n\nclass Mp4Sample {\n  public size: number;\n  public duration: number;\n  public cts: number;\n  public flags: Mp4SampleFlags;\n\n  constructor(\n    isKeyframe: boolean,\n    duration: number,\n    size: number,\n    cts: number,\n  ) {\n    this.duration = duration;\n    this.size = size;\n    this.cts = cts;\n    this.flags = {\n      isLeading: 0,\n      isDependedOn: 0,\n      hasRedundancy: 0,\n      degradPrio: 0,\n      dependsOn: isKeyframe ? 2 : 1,\n      isNonSync: isKeyframe ? 0 : 1,\n    };\n  }\n}\n", "import {\n  flushTextTrackMetadataCueSamples,\n  flushTextTrackUserdataCueSamples,\n} from './mp4-remuxer';\nimport {\n  InitData,\n  InitDataTrack,\n  patchEncyptionData,\n} from '../utils/mp4-tools';\nimport {\n  getDuration,\n  getStartDTS,\n  offsetStartDTS,\n  parseInitSegment,\n} from '../utils/mp4-tools';\nimport { ElementaryStreamTypes } from '../loader/fragment';\nimport { logger } from '../utils/logger';\nimport { getCodecCompatibleName } from '../utils/codecs';\nimport type { TrackSet } from '../types/track';\nimport type {\n  InitSegmentData,\n  RemuxedTrack,\n  Remuxer,\n  RemuxerResult,\n} from '../types/remuxer';\nimport type {\n  DemuxedAudioTrack,\n  DemuxedMetadataTrack,\n  DemuxedUserdataTrack,\n  PassthroughTrack,\n} from '../types/demuxer';\nimport type { DecryptData } from '../loader/level-key';\nimport type { RationalTimestamp } from '../utils/timescale-conversion';\n\nclass PassThroughRemuxer implements Remuxer {\n  private emitInitSegment: boolean = false;\n  private audioCodec?: string;\n  private videoCodec?: string;\n  private initData?: InitData;\n  private initPTS: RationalTimestamp | null = null;\n  private initTracks?: TrackSet;\n  private lastEndTime: number | null = null;\n\n  public destroy() {}\n\n  public resetTimeStamp(defaultInitPTS: RationalTimestamp | null) {\n    this.initPTS = defaultInitPTS;\n    this.lastEndTime = null;\n  }\n\n  public resetNextTimestamp() {\n    this.lastEndTime = null;\n  }\n\n  public resetInitSegment(\n    initSegment: Uint8Array | undefined,\n    audioCodec: string | undefined,\n    videoCodec: string | undefined,\n    decryptdata: DecryptData | null,\n  ) {\n    this.audioCodec = audioCodec;\n    this.videoCodec = videoCodec;\n    this.generateInitSegment(patchEncyptionData(initSegment, decryptdata));\n    this.emitInitSegment = true;\n  }\n\n  private generateInitSegment(initSegment: Uint8Array | undefined): void {\n    let { audioCodec, videoCodec } = this;\n    if (!initSegment?.byteLength) {\n      this.initTracks = undefined;\n      this.initData = undefined;\n      return;\n    }\n    const initData = (this.initData = parseInitSegment(initSegment));\n\n    // Get codec from initSegment or fallback to default\n    if (initData.audio) {\n      audioCodec = getParsedTrackCodec(\n        initData.audio,\n        ElementaryStreamTypes.AUDIO,\n      );\n    }\n\n    if (initData.video) {\n      videoCodec = getParsedTrackCodec(\n        initData.video,\n        ElementaryStreamTypes.VIDEO,\n      );\n    }\n\n    const tracks: TrackSet = {};\n    if (initData.audio && initData.video) {\n      tracks.audiovideo = {\n        container: 'video/mp4',\n        codec: audioCodec + ',' + videoCodec,\n        initSegment,\n        id: 'main',\n      };\n    } else if (initData.audio) {\n      tracks.audio = {\n        container: 'audio/mp4',\n        codec: audioCodec,\n        initSegment,\n        id: 'audio',\n      };\n    } else if (initData.video) {\n      tracks.video = {\n        container: 'video/mp4',\n        codec: videoCodec,\n        initSegment,\n        id: 'main',\n      };\n    } else {\n      logger.warn(\n        '[passthrough-remuxer.ts]: initSegment does not contain moov or trak boxes.',\n      );\n    }\n    this.initTracks = tracks;\n  }\n\n  public remux(\n    audioTrack: DemuxedAudioTrack,\n    videoTrack: PassthroughTrack,\n    id3Track: DemuxedMetadataTrack,\n    textTrack: DemuxedUserdataTrack,\n    timeOffset: number,\n    accurateTimeOffset: boolean,\n  ): RemuxerResult {\n    let { initPTS, lastEndTime } = this;\n    const result: RemuxerResult = {\n      audio: undefined,\n      video: undefined,\n      text: textTrack,\n      id3: id3Track,\n      initSegment: undefined,\n    };\n\n    // If we haven't yet set a lastEndDTS, or it was reset, set it to the provided timeOffset. We want to use the\n    // lastEndDTS over timeOffset whenever possible; during progressive playback, the media source will not update\n    // the media duration (which is what timeOffset is provided as) before we need to process the next chunk.\n    if (!Number.isFinite(lastEndTime!)) {\n      lastEndTime = this.lastEndTime = timeOffset || 0;\n    }\n\n    // The binary segment data is added to the videoTrack in the mp4demuxer. We don't check to see if the data is only\n    // audio or video (or both); adding it to video was an arbitrary choice.\n    const data = videoTrack.samples;\n    if (!data?.length) {\n      return result;\n    }\n\n    const initSegment: InitSegmentData = {\n      initPTS: undefined,\n      timescale: 1,\n    };\n    let initData = this.initData;\n    if (!initData?.length) {\n      this.generateInitSegment(data);\n      initData = this.initData;\n    }\n    if (!initData?.length) {\n      // We can't remux if the initSegment could not be generated\n      logger.warn('[passthrough-remuxer.ts]: Failed to generate initSegment.');\n      return result;\n    }\n    if (this.emitInitSegment) {\n      initSegment.tracks = this.initTracks as TrackSet;\n      this.emitInitSegment = false;\n    }\n\n    const duration = getDuration(data, initData);\n    const startDTS = getStartDTS(initData, data);\n    const decodeTime = startDTS === null ? timeOffset : startDTS;\n    if (\n      isInvalidInitPts(initPTS, decodeTime, timeOffset, duration) ||\n      (initSegment.timescale !== initPTS.timescale && accurateTimeOffset)\n    ) {\n      initSegment.initPTS = decodeTime - timeOffset;\n      if (initPTS && initPTS.timescale === 1) {\n        logger.warn(\n          `Adjusting initPTS by ${initSegment.initPTS - initPTS.baseTime}`,\n        );\n      }\n      this.initPTS = initPTS = {\n        baseTime: initSegment.initPTS,\n        timescale: 1,\n      };\n    }\n\n    const startTime = audioTrack\n      ? decodeTime - initPTS.baseTime / initPTS.timescale\n      : (lastEndTime as number);\n    const endTime = startTime + duration;\n    offsetStartDTS(initData, data, initPTS.baseTime / initPTS.timescale);\n\n    if (duration > 0) {\n      this.lastEndTime = endTime;\n    } else {\n      logger.warn('Duration parsed from mp4 should be greater than zero');\n      this.resetNextTimestamp();\n    }\n\n    const hasAudio = !!initData.audio;\n    const hasVideo = !!initData.video;\n\n    let type: any = '';\n    if (hasAudio) {\n      type += 'audio';\n    }\n\n    if (hasVideo) {\n      type += 'video';\n    }\n\n    const track: RemuxedTrack = {\n      data1: data,\n      startPTS: startTime,\n      startDTS: startTime,\n      endPTS: endTime,\n      endDTS: endTime,\n      type,\n      hasAudio,\n      hasVideo,\n      nb: 1,\n      dropped: 0,\n    };\n\n    result.audio = track.type === 'audio' ? track : undefined;\n    result.video = track.type !== 'audio' ? track : undefined;\n    result.initSegment = initSegment;\n    result.id3 = flushTextTrackMetadataCueSamples(\n      id3Track,\n      timeOffset,\n      initPTS,\n      initPTS,\n    );\n\n    if (textTrack.samples.length) {\n      result.text = flushTextTrackUserdataCueSamples(\n        textTrack,\n        timeOffset,\n        initPTS,\n      );\n    }\n\n    return result;\n  }\n}\n\nfunction isInvalidInitPts(\n  initPTS: RationalTimestamp | null,\n  startDTS: number,\n  timeOffset: number,\n  duration: number,\n): initPTS is null {\n  if (initPTS === null) {\n    return true;\n  }\n  // InitPTS is invalid when distance from program would be more than segment duration or a minimum of one second\n  const minDuration = Math.max(duration, 1);\n  const startTime = startDTS - initPTS.baseTime / initPTS.timescale;\n  return Math.abs(startTime - timeOffset) > minDuration;\n}\n\nfunction getParsedTrackCodec(\n  track: InitDataTrack,\n  type: ElementaryStreamTypes.AUDIO | ElementaryStreamTypes.VIDEO,\n): string {\n  const parsedCodec = track?.codec;\n  if (parsedCodec && parsedCodec.length > 4) {\n    return parsedCodec;\n  }\n  if (type === ElementaryStreamTypes.AUDIO) {\n    if (\n      parsedCodec === 'ec-3' ||\n      parsedCodec === 'ac-3' ||\n      parsedCodec === 'alac'\n    ) {\n      return parsedCodec;\n    }\n    if (parsedCodec === 'fLaC' || parsedCodec === 'Opus') {\n      // Opting not to get `preferManagedMediaSource` from player config for isSupported() check for simplicity\n      const preferManagedMediaSource = false;\n      return getCodecCompatibleName(parsedCodec, preferManagedMediaSource);\n    }\n    const result = 'mp4a.40.5';\n    logger.info(\n      `Parsed audio codec \"${parsedCodec}\" or audio object type not handled. Using \"${result}\"`,\n    );\n    return result;\n  }\n  // Provide defaults based on codec type\n  // This allows for some playback of some fmp4 playlists without CODECS defined in manifest\n  logger.warn(`Unhandled video codec \"${parsedCodec}\"`);\n  if (parsedCodec === 'hvc1' || parsedCodec === 'hev1') {\n    return 'hvc1.1.6.L120.90';\n  }\n  if (parsedCodec === 'av01') {\n    return 'av01.0.04M.08';\n  }\n  return 'avc1.42e01e';\n}\nexport default PassThroughRemuxer;\n", "import type { HlsEventEmitter } from '../events';\nimport { Events } from '../events';\nimport { ErrorTypes, ErrorDetails } from '../errors';\nimport Decrypter from '../crypt/decrypter';\nimport AACDemuxer from './audio/aacdemuxer';\nimport MP4Demuxer from '../demux/mp4demuxer';\nimport TSDemuxer, { TypeSupported } from '../demux/tsdemuxer';\nimport MP3Demuxer from './audio/mp3demuxer';\nimport { AC3Demuxer } from './audio/ac3-demuxer';\nimport MP4Remuxer from '../remux/mp4-remuxer';\nimport PassThroughRemuxer from '../remux/passthrough-remuxer';\nimport { logger } from '../utils/logger';\nimport type { Demuxer, DemuxerResult, KeyData } from '../types/demuxer';\nimport type { Remuxer } from '../types/remuxer';\nimport type { TransmuxerResult, ChunkMetadata } from '../types/transmuxer';\nimport type { HlsConfig } from '../config';\nimport type { DecryptData } from '../loader/level-key';\nimport type { PlaylistLevelType } from '../types/loader';\nimport type { RationalTimestamp } from '../utils/timescale-conversion';\nimport { optionalSelf } from '../utils/global';\n\nlet now;\n// performance.now() not available on WebWorker, at least on Safari Desktop\ntry {\n  now = self.performance.now.bind(self.performance);\n} catch (err) {\n  logger.debug('Unable to use Performance API on this environment');\n  now = optionalSelf?.Date.now;\n}\n\ntype MuxConfig =\n  | { demux: typeof MP4Demuxer; remux: typeof PassThroughRemuxer }\n  | { demux: typeof TSDemuxer; remux: typeof MP4Remuxer }\n  | { demux: typeof AC3Demuxer; remux: typeof MP4Remuxer }\n  | { demux: typeof AACDemuxer; remux: typeof MP4Remuxer }\n  | { demux: typeof MP3Demuxer; remux: typeof MP4Remuxer };\n\nconst muxConfig: MuxConfig[] = [\n  { demux: MP4Demuxer, remux: PassThroughRemuxer },\n  { demux: TSDemuxer, remux: MP4Remuxer },\n  { demux: AACDemuxer, remux: MP4Remuxer },\n  { demux: MP3Demuxer, remux: MP4Remuxer },\n];\n\nif (__USE_M2TS_ADVANCED_CODECS__) {\n  muxConfig.splice(2, 0, { demux: AC3Demuxer, remux: MP4Remuxer });\n}\n\nexport default class Transmuxer {\n  public async: boolean = false;\n  private observer: HlsEventEmitter;\n  private typeSupported: TypeSupported;\n  private config: HlsConfig;\n  private vendor: string;\n  private id: PlaylistLevelType;\n  private demuxer?: Demuxer;\n  private remuxer?: Remuxer;\n  private decrypter?: Decrypter;\n  private probe!: Function;\n  private decryptionPromise: Promise<TransmuxerResult> | null = null;\n  private transmuxConfig!: TransmuxConfig;\n  private currentTransmuxState!: TransmuxState;\n\n  constructor(\n    observer: HlsEventEmitter,\n    typeSupported: TypeSupported,\n    config: HlsConfig,\n    vendor: string,\n    id: PlaylistLevelType,\n  ) {\n    this.observer = observer;\n    this.typeSupported = typeSupported;\n    this.config = config;\n    this.vendor = vendor;\n    this.id = id;\n  }\n\n  configure(transmuxConfig: TransmuxConfig) {\n    this.transmuxConfig = transmuxConfig;\n    if (this.decrypter) {\n      this.decrypter.reset();\n    }\n  }\n\n  push(\n    data: ArrayBuffer,\n    decryptdata: DecryptData | null,\n    chunkMeta: ChunkMetadata,\n    state?: TransmuxState,\n  ): TransmuxerResult | Promise<TransmuxerResult> {\n    const stats = chunkMeta.transmuxing;\n    stats.executeStart = now();\n\n    let uintData: Uint8Array = new Uint8Array(data);\n    const { currentTransmuxState, transmuxConfig } = this;\n    if (state) {\n      this.currentTransmuxState = state;\n    }\n\n    const {\n      contiguous,\n      discontinuity,\n      trackSwitch,\n      accurateTimeOffset,\n      timeOffset,\n      initSegmentChange,\n    } = state || currentTransmuxState;\n    const {\n      audioCodec,\n      videoCodec,\n      defaultInitPts,\n      duration,\n      initSegmentData,\n    } = transmuxConfig;\n\n    const keyData = getEncryptionType(uintData, decryptdata);\n    if (keyData && keyData.method === 'AES-128') {\n      const decrypter = this.getDecrypter();\n      // Software decryption is synchronous; webCrypto is not\n      if (decrypter.isSync()) {\n        // Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached\n        // data is handled in the flush() call\n        let decryptedData = decrypter.softwareDecrypt(\n          uintData,\n          keyData.key.buffer,\n          keyData.iv.buffer,\n        );\n        // For Low-Latency HLS Parts, decrypt in place, since part parsing is expected on push progress\n        const loadingParts = chunkMeta.part > -1;\n        if (loadingParts) {\n          decryptedData = decrypter.flush();\n        }\n        if (!decryptedData) {\n          stats.executeEnd = now();\n          return emptyResult(chunkMeta);\n        }\n        uintData = new Uint8Array(decryptedData);\n      } else {\n        this.decryptionPromise = decrypter\n          .webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer)\n          .then((decryptedData): TransmuxerResult => {\n            // Calling push here is important; if flush() is called while this is still resolving, this ensures that\n            // the decrypted data has been transmuxed\n            const result = this.push(\n              decryptedData,\n              null,\n              chunkMeta,\n            ) as TransmuxerResult;\n            this.decryptionPromise = null;\n            return result;\n          });\n        return this.decryptionPromise!;\n      }\n    }\n\n    const resetMuxers = this.needsProbing(discontinuity, trackSwitch);\n    if (resetMuxers) {\n      const error = this.configureTransmuxer(uintData);\n      if (error) {\n        logger.warn(`[transmuxer] ${error.message}`);\n        this.observer.emit(Events.ERROR, Events.ERROR, {\n          type: ErrorTypes.MEDIA_ERROR,\n          details: ErrorDetails.FRAG_PARSING_ERROR,\n          fatal: false,\n          error,\n          reason: error.message,\n        });\n        stats.executeEnd = now();\n        return emptyResult(chunkMeta);\n      }\n    }\n\n    if (discontinuity || trackSwitch || initSegmentChange || resetMuxers) {\n      this.resetInitSegment(\n        initSegmentData,\n        audioCodec,\n        videoCodec,\n        duration,\n        decryptdata,\n      );\n    }\n\n    if (discontinuity || initSegmentChange || resetMuxers) {\n      this.resetInitialTimestamp(defaultInitPts);\n    }\n\n    if (!contiguous) {\n      this.resetContiguity();\n    }\n\n    const result = this.transmux(\n      uintData,\n      keyData,\n      timeOffset,\n      accurateTimeOffset,\n      chunkMeta,\n    );\n    const currentState = this.currentTransmuxState;\n\n    currentState.contiguous = true;\n    currentState.discontinuity = false;\n    currentState.trackSwitch = false;\n\n    stats.executeEnd = now();\n    return result;\n  }\n\n  // Due to data caching, flush calls can produce more than one TransmuxerResult (hence the Array type)\n  flush(\n    chunkMeta: ChunkMetadata,\n  ): TransmuxerResult[] | Promise<TransmuxerResult[]> {\n    const stats = chunkMeta.transmuxing;\n    stats.executeStart = now();\n\n    const { decrypter, currentTransmuxState, decryptionPromise } = this;\n\n    if (decryptionPromise) {\n      // Upon resolution, the decryption promise calls push() and returns its TransmuxerResult up the stack. Therefore\n      // only flushing is required for async decryption\n      return decryptionPromise.then(() => {\n        return this.flush(chunkMeta);\n      });\n    }\n\n    const transmuxResults: TransmuxerResult[] = [];\n    const { timeOffset } = currentTransmuxState;\n    if (decrypter) {\n      // The decrypter may have data cached, which needs to be demuxed. In this case we'll have two TransmuxResults\n      // This happens in the case that we receive only 1 push call for a segment (either for non-progressive downloads,\n      // or for progressive downloads with small segments)\n      const decryptedData = decrypter.flush();\n      if (decryptedData) {\n        // Push always returns a TransmuxerResult if decryptdata is null\n        transmuxResults.push(\n          this.push(decryptedData, null, chunkMeta) as TransmuxerResult,\n        );\n      }\n    }\n\n    const { demuxer, remuxer } = this;\n    if (!demuxer || !remuxer) {\n      // If probing failed, then Hls.js has been given content its not able to handle\n      stats.executeEnd = now();\n      return [emptyResult(chunkMeta)];\n    }\n\n    const demuxResultOrPromise = demuxer.flush(timeOffset);\n    if (isPromise(demuxResultOrPromise)) {\n      // Decrypt final SAMPLE-AES samples\n      return demuxResultOrPromise.then((demuxResult) => {\n        this.flushRemux(transmuxResults, demuxResult, chunkMeta);\n        return transmuxResults;\n      });\n    }\n\n    this.flushRemux(transmuxResults, demuxResultOrPromise, chunkMeta);\n    return transmuxResults;\n  }\n\n  private flushRemux(\n    transmuxResults: TransmuxerResult[],\n    demuxResult: DemuxerResult,\n    chunkMeta: ChunkMetadata,\n  ) {\n    const { audioTrack, videoTrack, id3Track, textTrack } = demuxResult;\n    const { accurateTimeOffset, timeOffset } = this.currentTransmuxState;\n    logger.log(\n      `[transmuxer.ts]: Flushed fragment ${chunkMeta.sn}${\n        chunkMeta.part > -1 ? ' p: ' + chunkMeta.part : ''\n      } of level ${chunkMeta.level}`,\n    );\n    const remuxResult = this.remuxer!.remux(\n      audioTrack,\n      videoTrack,\n      id3Track,\n      textTrack,\n      timeOffset,\n      accurateTimeOffset,\n      true,\n      this.id,\n    );\n    transmuxResults.push({\n      remuxResult,\n      chunkMeta,\n    });\n\n    chunkMeta.transmuxing.executeEnd = now();\n  }\n\n  resetInitialTimestamp(defaultInitPts: RationalTimestamp | null) {\n    const { demuxer, remuxer } = this;\n    if (!demuxer || !remuxer) {\n      return;\n    }\n    demuxer.resetTimeStamp(defaultInitPts);\n    remuxer.resetTimeStamp(defaultInitPts);\n  }\n\n  resetContiguity() {\n    const { demuxer, remuxer } = this;\n    if (!demuxer || !remuxer) {\n      return;\n    }\n    demuxer.resetContiguity();\n    remuxer.resetNextTimestamp();\n  }\n\n  resetInitSegment(\n    initSegmentData: Uint8Array | undefined,\n    audioCodec: string | undefined,\n    videoCodec: string | undefined,\n    trackDuration: number,\n    decryptdata: DecryptData | null,\n  ) {\n    const { demuxer, remuxer } = this;\n    if (!demuxer || !remuxer) {\n      return;\n    }\n    demuxer.resetInitSegment(\n      initSegmentData,\n      audioCodec,\n      videoCodec,\n      trackDuration,\n    );\n    remuxer.resetInitSegment(\n      initSegmentData,\n      audioCodec,\n      videoCodec,\n      decryptdata,\n    );\n  }\n\n  destroy(): void {\n    if (this.demuxer) {\n      this.demuxer.destroy();\n      this.demuxer = undefined;\n    }\n    if (this.remuxer) {\n      this.remuxer.destroy();\n      this.remuxer = undefined;\n    }\n  }\n\n  private transmux(\n    data: Uint8Array,\n    keyData: KeyData | null,\n    timeOffset: number,\n    accurateTimeOffset: boolean,\n    chunkMeta: ChunkMetadata,\n  ): TransmuxerResult | Promise<TransmuxerResult> {\n    let result: TransmuxerResult | Promise<TransmuxerResult>;\n    if (keyData && keyData.method === 'SAMPLE-AES') {\n      result = this.transmuxSampleAes(\n        data,\n        keyData,\n        timeOffset,\n        accurateTimeOffset,\n        chunkMeta,\n      );\n    } else {\n      result = this.transmuxUnencrypted(\n        data,\n        timeOffset,\n        accurateTimeOffset,\n        chunkMeta,\n      );\n    }\n    return result;\n  }\n\n  private transmuxUnencrypted(\n    data: Uint8Array,\n    timeOffset: number,\n    accurateTimeOffset: boolean,\n    chunkMeta: ChunkMetadata,\n  ): TransmuxerResult {\n    const { audioTrack, videoTrack, id3Track, textTrack } = (\n      this.demuxer as Demuxer\n    ).demux(data, timeOffset, false, !this.config.progressive);\n    const remuxResult = this.remuxer!.remux(\n      audioTrack,\n      videoTrack,\n      id3Track,\n      textTrack,\n      timeOffset,\n      accurateTimeOffset,\n      false,\n      this.id,\n    );\n    return {\n      remuxResult,\n      chunkMeta,\n    };\n  }\n\n  private transmuxSampleAes(\n    data: Uint8Array,\n    decryptData: KeyData,\n    timeOffset: number,\n    accurateTimeOffset: boolean,\n    chunkMeta: ChunkMetadata,\n  ): Promise<TransmuxerResult> {\n    return (this.demuxer as Demuxer)\n      .demuxSampleAes(data, decryptData, timeOffset)\n      .then((demuxResult) => {\n        const remuxResult = this.remuxer!.remux(\n          demuxResult.audioTrack,\n          demuxResult.videoTrack,\n          demuxResult.id3Track,\n          demuxResult.textTrack,\n          timeOffset,\n          accurateTimeOffset,\n          false,\n          this.id,\n        );\n        return {\n          remuxResult,\n          chunkMeta,\n        };\n      });\n  }\n\n  private configureTransmuxer(data: Uint8Array): void | Error {\n    const { config, observer, typeSupported, vendor } = this;\n    // probe for content type\n    let mux;\n    for (let i = 0, len = muxConfig.length; i < len; i++) {\n      if (muxConfig[i].demux?.probe(data)) {\n        mux = muxConfig[i];\n        break;\n      }\n    }\n    if (!mux) {\n      return new Error('Failed to find demuxer by probing fragment data');\n    }\n    // so let's check that current remuxer and demuxer are still valid\n    const demuxer = this.demuxer;\n    const remuxer = this.remuxer;\n    const Remuxer: MuxConfig['remux'] = mux.remux;\n    const Demuxer: MuxConfig['demux'] = mux.demux;\n    if (!remuxer || !(remuxer instanceof Remuxer)) {\n      this.remuxer = new Remuxer(observer, config, typeSupported, vendor);\n    }\n    if (!demuxer || !(demuxer instanceof Demuxer)) {\n      this.demuxer = new Demuxer(observer, config, typeSupported);\n      this.probe = Demuxer.probe;\n    }\n  }\n\n  private needsProbing(discontinuity: boolean, trackSwitch: boolean): boolean {\n    // in case of continuity change, or track switch\n    // we might switch from content type (AAC container to TS container, or TS to fmp4 for example)\n    return !this.demuxer || !this.remuxer || discontinuity || trackSwitch;\n  }\n\n  private getDecrypter(): Decrypter {\n    let decrypter = this.decrypter;\n    if (!decrypter) {\n      decrypter = this.decrypter = new Decrypter(this.config);\n    }\n    return decrypter;\n  }\n}\n\nfunction getEncryptionType(\n  data: Uint8Array,\n  decryptData: DecryptData | null,\n): KeyData | null {\n  let encryptionType: KeyData | null = null;\n  if (\n    data.byteLength > 0 &&\n    decryptData?.key != null &&\n    decryptData.iv !== null &&\n    decryptData.method != null\n  ) {\n    encryptionType = decryptData as KeyData;\n  }\n  return encryptionType;\n}\n\nconst emptyResult = (chunkMeta): TransmuxerResult => ({\n  remuxResult: {},\n  chunkMeta,\n});\n\nexport function isPromise<T>(p: Promise<T> | any): p is Promise<T> {\n  return 'then' in p && p.then instanceof Function;\n}\n\nexport class TransmuxConfig {\n  public audioCodec?: string;\n  public videoCodec?: string;\n  public initSegmentData?: Uint8Array;\n  public duration: number;\n  public defaultInitPts: RationalTimestamp | null;\n\n  constructor(\n    audioCodec: string | undefined,\n    videoCodec: string | undefined,\n    initSegmentData: Uint8Array | undefined,\n    duration: number,\n    defaultInitPts?: RationalTimestamp,\n  ) {\n    this.audioCodec = audioCodec;\n    this.videoCodec = videoCodec;\n    this.initSegmentData = initSegmentData;\n    this.duration = duration;\n    this.defaultInitPts = defaultInitPts || null;\n  }\n}\n\nexport class TransmuxState {\n  public discontinuity: boolean;\n  public contiguous: boolean;\n  public accurateTimeOffset: boolean;\n  public trackSwitch: boolean;\n  public timeOffset: number;\n  public initSegmentChange: boolean;\n\n  constructor(\n    discontinuity: boolean,\n    contiguous: boolean,\n    accurateTimeOffset: boolean,\n    trackSwitch: boolean,\n    timeOffset: number,\n    initSegmentChange: boolean,\n  ) {\n    this.discontinuity = discontinuity;\n    this.contiguous = contiguous;\n    this.accurateTimeOffset = accurateTimeOffset;\n    this.trackSwitch = trackSwitch;\n    this.timeOffset = timeOffset;\n    this.initSegmentChange = initSegmentChange;\n  }\n}\n", "'use strict';\n\nvar has = Object.prototype.hasOwnProperty\n  , prefix = '~';\n\n/**\n * Constructor to create a storage for our `EE` objects.\n * An `Events` instance is a plain object whose properties are event names.\n *\n * @constructor\n * @private\n */\nfunction Events() {}\n\n//\n// We try to not inherit from `Object.prototype`. In some engines creating an\n// instance in this way is faster than calling `Object.create(null)` directly.\n// If `Object.create(null)` is not supported we prefix the event names with a\n// character to make sure that the built-in object properties are not\n// overridden or used as an attack vector.\n//\nif (Object.create) {\n  Events.prototype = Object.create(null);\n\n  //\n  // This hack is needed because the `__proto__` property is still inherited in\n  // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.\n  //\n  if (!new Events().__proto__) prefix = false;\n}\n\n/**\n * Representation of a single event listener.\n *\n * @param {Function} fn The listener function.\n * @param {*} context The context to invoke the listener with.\n * @param {Boolean} [once=false] Specify if the listener is a one-time listener.\n * @constructor\n * @private\n */\nfunction EE(fn, context, once) {\n  this.fn = fn;\n  this.context = context;\n  this.once = once || false;\n}\n\n/**\n * Add a listener for a given event.\n *\n * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.\n * @param {(String|Symbol)} event The event name.\n * @param {Function} fn The listener function.\n * @param {*} context The context to invoke the listener with.\n * @param {Boolean} once Specify if the listener is a one-time listener.\n * @returns {EventEmitter}\n * @private\n */\nfunction addListener(emitter, event, fn, context, once) {\n  if (typeof fn !== 'function') {\n    throw new TypeError('The listener must be a function');\n  }\n\n  var listener = new EE(fn, context || emitter, once)\n    , evt = prefix ? prefix + event : event;\n\n  if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;\n  else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);\n  else emitter._events[evt] = [emitter._events[evt], listener];\n\n  return emitter;\n}\n\n/**\n * Clear event by name.\n *\n * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.\n * @param {(String|Symbol)} evt The Event name.\n * @private\n */\nfunction clearEvent(emitter, evt) {\n  if (--emitter._eventsCount === 0) emitter._events = new Events();\n  else delete emitter._events[evt];\n}\n\n/**\n * Minimal `EventEmitter` interface that is molded against the Node.js\n * `EventEmitter` interface.\n *\n * @constructor\n * @public\n */\nfunction EventEmitter() {\n  this._events = new Events();\n  this._eventsCount = 0;\n}\n\n/**\n * Return an array listing the events for which the emitter has registered\n * listeners.\n *\n * @returns {Array}\n * @public\n */\nEventEmitter.prototype.eventNames = function eventNames() {\n  var names = []\n    , events\n    , name;\n\n  if (this._eventsCount === 0) return names;\n\n  for (name in (events = this._events)) {\n    if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);\n  }\n\n  if (Object.getOwnPropertySymbols) {\n    return names.concat(Object.getOwnPropertySymbols(events));\n  }\n\n  return names;\n};\n\n/**\n * Return the listeners registered for a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @returns {Array} The registered listeners.\n * @public\n */\nEventEmitter.prototype.listeners = function listeners(event) {\n  var evt = prefix ? prefix + event : event\n    , handlers = this._events[evt];\n\n  if (!handlers) return [];\n  if (handlers.fn) return [handlers.fn];\n\n  for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {\n    ee[i] = handlers[i].fn;\n  }\n\n  return ee;\n};\n\n/**\n * Return the number of listeners listening to a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @returns {Number} The number of listeners.\n * @public\n */\nEventEmitter.prototype.listenerCount = function listenerCount(event) {\n  var evt = prefix ? prefix + event : event\n    , listeners = this._events[evt];\n\n  if (!listeners) return 0;\n  if (listeners.fn) return 1;\n  return listeners.length;\n};\n\n/**\n * Calls each of the listeners registered for a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @returns {Boolean} `true` if the event had listeners, else `false`.\n * @public\n */\nEventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {\n  var evt = prefix ? prefix + event : event;\n\n  if (!this._events[evt]) return false;\n\n  var listeners = this._events[evt]\n    , len = arguments.length\n    , args\n    , i;\n\n  if (listeners.fn) {\n    if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);\n\n    switch (len) {\n      case 1: return listeners.fn.call(listeners.context), true;\n      case 2: return listeners.fn.call(listeners.context, a1), true;\n      case 3: return listeners.fn.call(listeners.context, a1, a2), true;\n      case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;\n      case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;\n      case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;\n    }\n\n    for (i = 1, args = new Array(len -1); i < len; i++) {\n      args[i - 1] = arguments[i];\n    }\n\n    listeners.fn.apply(listeners.context, args);\n  } else {\n    var length = listeners.length\n      , j;\n\n    for (i = 0; i < length; i++) {\n      if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);\n\n      switch (len) {\n        case 1: listeners[i].fn.call(listeners[i].context); break;\n        case 2: listeners[i].fn.call(listeners[i].context, a1); break;\n        case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;\n        case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;\n        default:\n          if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {\n            args[j - 1] = arguments[j];\n          }\n\n          listeners[i].fn.apply(listeners[i].context, args);\n      }\n    }\n  }\n\n  return true;\n};\n\n/**\n * Add a listener for a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @param {Function} fn The listener function.\n * @param {*} [context=this] The context to invoke the listener with.\n * @returns {EventEmitter} `this`.\n * @public\n */\nEventEmitter.prototype.on = function on(event, fn, context) {\n  return addListener(this, event, fn, context, false);\n};\n\n/**\n * Add a one-time listener for a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @param {Function} fn The listener function.\n * @param {*} [context=this] The context to invoke the listener with.\n * @returns {EventEmitter} `this`.\n * @public\n */\nEventEmitter.prototype.once = function once(event, fn, context) {\n  return addListener(this, event, fn, context, true);\n};\n\n/**\n * Remove the listeners of a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @param {Function} fn Only remove the listeners that match this function.\n * @param {*} context Only remove the listeners that have this context.\n * @param {Boolean} once Only remove one-time listeners.\n * @returns {EventEmitter} `this`.\n * @public\n */\nEventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {\n  var evt = prefix ? prefix + event : event;\n\n  if (!this._events[evt]) return this;\n  if (!fn) {\n    clearEvent(this, evt);\n    return this;\n  }\n\n  var listeners = this._events[evt];\n\n  if (listeners.fn) {\n    if (\n      listeners.fn === fn &&\n      (!once || listeners.once) &&\n      (!context || listeners.context === context)\n    ) {\n      clearEvent(this, evt);\n    }\n  } else {\n    for (var i = 0, events = [], length = listeners.length; i < length; i++) {\n      if (\n        listeners[i].fn !== fn ||\n        (once && !listeners[i].once) ||\n        (context && listeners[i].context !== context)\n      ) {\n        events.push(listeners[i]);\n      }\n    }\n\n    //\n    // Reset the array, or remove it completely if we have no more listeners.\n    //\n    if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;\n    else clearEvent(this, evt);\n  }\n\n  return this;\n};\n\n/**\n * Remove all listeners, or those of the specified event.\n *\n * @param {(String|Symbol)} [event] The event name.\n * @returns {EventEmitter} `this`.\n * @public\n */\nEventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {\n  var evt;\n\n  if (event) {\n    evt = prefix ? prefix + event : event;\n    if (this._events[evt]) clearEvent(this, evt);\n  } else {\n    this._events = new Events();\n    this._eventsCount = 0;\n  }\n\n  return this;\n};\n\n//\n// Alias methods names because people roll like that.\n//\nEventEmitter.prototype.off = EventEmitter.prototype.removeListener;\nEventEmitter.prototype.addListener = EventEmitter.prototype.on;\n\n//\n// Expose the prefix.\n//\nEventEmitter.prefixed = prefix;\n\n//\n// Allow `EventEmitter` to be imported as module namespace.\n//\nEventEmitter.EventEmitter = EventEmitter;\n\n//\n// Expose the module.\n//\nif ('undefined' !== typeof module) {\n  module.exports = EventEmitter;\n}\n", "import {\n  WorkerContext,\n  hasUMDWorker,\n  injectWorker,\n  loadWorker,\n} from './inject-worker';\nimport { Events } from '../events';\nimport Transmuxer, {\n  TransmuxConfig,\n  TransmuxState,\n  isPromise,\n} from '../demux/transmuxer';\nimport { logger } from '../utils/logger';\nimport { ErrorTypes, ErrorDetails } from '../errors';\nimport { getMediaSource } from '../utils/mediasource-helper';\nimport { EventEmitter } from 'eventemitter3';\nimport { Fragment, Part } from '../loader/fragment';\nimport type { ChunkMetadata, TransmuxerResult } from '../types/transmuxer';\nimport type Hls from '../hls';\nimport type { HlsEventEmitter, HlsListeners } from '../events';\nimport type { PlaylistLevelType } from '../types/loader';\nimport type { TypeSupported } from './tsdemuxer';\nimport type { RationalTimestamp } from '../utils/timescale-conversion';\n\nexport default class TransmuxerInterface {\n  public error: Error | null = null;\n  private hls: Hls;\n  private id: PlaylistLevelType;\n  private observer: HlsEventEmitter;\n  private frag: Fragment | null = null;\n  private part: Part | null = null;\n  private useWorker: boolean;\n  private workerContext: WorkerContext | null = null;\n  private onwmsg?: (\n    event: MessageEvent<{ event: string; data?: any } | null>,\n  ) => void;\n  private transmuxer: Transmuxer | null = null;\n  private onTransmuxComplete: (transmuxResult: TransmuxerResult) => void;\n  private onFlush: (chunkMeta: ChunkMetadata) => void;\n\n  constructor(\n    hls: Hls,\n    id: PlaylistLevelType,\n    onTransmuxComplete: (transmuxResult: TransmuxerResult) => void,\n    onFlush: (chunkMeta: ChunkMetadata) => void,\n  ) {\n    const config = hls.config;\n    this.hls = hls;\n    this.id = id;\n    this.useWorker = !!config.enableWorker;\n    this.onTransmuxComplete = onTransmuxComplete;\n    this.onFlush = onFlush;\n\n    const forwardMessage = (ev, data) => {\n      data = data || {};\n      data.frag = this.frag;\n      data.id = this.id;\n      if (ev === Events.ERROR) {\n        this.error = data.error;\n      }\n      this.hls.trigger(ev, data);\n    };\n\n    // forward events to main thread\n    this.observer = new EventEmitter() as HlsEventEmitter;\n    this.observer.on(Events.FRAG_DECRYPTED, forwardMessage);\n    this.observer.on(Events.ERROR, forwardMessage);\n\n    const MediaSource = getMediaSource(config.preferManagedMediaSource) || {\n      isTypeSupported: () => false,\n    };\n    const m2tsTypeSupported: TypeSupported = {\n      mpeg: MediaSource.isTypeSupported('audio/mpeg'),\n      mp3: MediaSource.isTypeSupported('audio/mp4; codecs=\"mp3\"'),\n      ac3: __USE_M2TS_ADVANCED_CODECS__\n        ? MediaSource.isTypeSupported('audio/mp4; codecs=\"ac-3\"')\n        : false,\n    };\n\n    if (this.useWorker && typeof Worker !== 'undefined') {\n      const canCreateWorker = config.workerPath || hasUMDWorker();\n      if (canCreateWorker) {\n        try {\n          if (config.workerPath) {\n            logger.log(`loading Web Worker ${config.workerPath} for \"${id}\"`);\n            this.workerContext = loadWorker(config.workerPath);\n          } else {\n            logger.log(`injecting Web Worker for \"${id}\"`);\n            this.workerContext = injectWorker();\n          }\n          this.onwmsg = (event) => this.onWorkerMessage(event);\n          const { worker } = this.workerContext;\n          worker.addEventListener('message', this.onwmsg);\n          worker.onerror = (event) => {\n            const error = new Error(\n              `${event.message}  (${event.filename}:${event.lineno})`,\n            );\n            config.enableWorker = false;\n            logger.warn(`Error in \"${id}\" Web Worker, fallback to inline`);\n            this.hls.trigger(Events.ERROR, {\n              type: ErrorTypes.OTHER_ERROR,\n              details: ErrorDetails.INTERNAL_EXCEPTION,\n              fatal: false,\n              event: 'demuxerWorker',\n              error,\n            });\n          };\n          worker.postMessage({\n            cmd: 'init',\n            typeSupported: m2tsTypeSupported,\n            vendor: '',\n            id: id,\n            config: JSON.stringify(config),\n          });\n        } catch (err) {\n          logger.warn(\n            `Error setting up \"${id}\" Web Worker, fallback to inline`,\n            err,\n          );\n          this.resetWorker();\n          this.error = null;\n          this.transmuxer = new Transmuxer(\n            this.observer,\n            m2tsTypeSupported,\n            config,\n            '',\n            id,\n          );\n        }\n        return;\n      }\n    }\n\n    this.transmuxer = new Transmuxer(\n      this.observer,\n      m2tsTypeSupported,\n      config,\n      '',\n      id,\n    );\n  }\n\n  resetWorker() {\n    if (this.workerContext) {\n      const { worker, objectURL } = this.workerContext;\n      if (objectURL) {\n        // revoke the Object URL that was used to create transmuxer worker, so as not to leak it\n        self.URL.revokeObjectURL(objectURL);\n      }\n      worker.removeEventListener('message', this.onwmsg as any);\n      worker.onerror = null;\n      worker.terminate();\n      this.workerContext = null;\n    }\n  }\n\n  destroy() {\n    if (this.workerContext) {\n      this.resetWorker();\n      this.onwmsg = undefined;\n    } else {\n      const transmuxer = this.transmuxer;\n      if (transmuxer) {\n        transmuxer.destroy();\n        this.transmuxer = null;\n      }\n    }\n    const observer = this.observer;\n    if (observer) {\n      observer.removeAllListeners();\n    }\n    this.frag = null;\n    // @ts-ignore\n    this.observer = null;\n    // @ts-ignore\n    this.hls = null;\n  }\n\n  push(\n    data: ArrayBuffer,\n    initSegmentData: Uint8Array | undefined,\n    audioCodec: string | undefined,\n    videoCodec: string | undefined,\n    frag: Fragment,\n    part: Part | null,\n    duration: number,\n    accurateTimeOffset: boolean,\n    chunkMeta: ChunkMetadata,\n    defaultInitPTS?: RationalTimestamp,\n  ) {\n    chunkMeta.transmuxing.start = self.performance.now();\n    const { transmuxer } = this;\n    const timeOffset = part ? part.start : frag.start;\n    // TODO: push \"clear-lead\" decrypt data for unencrypted fragments in streams with encrypted ones\n    const decryptdata = frag.decryptdata;\n    const lastFrag = this.frag;\n\n    const discontinuity = !(lastFrag && frag.cc === lastFrag.cc);\n    const trackSwitch = !(lastFrag && chunkMeta.level === lastFrag.level);\n    const snDiff = lastFrag ? chunkMeta.sn - (lastFrag.sn as number) : -1;\n    const partDiff = this.part ? chunkMeta.part - this.part.index : -1;\n    const progressive =\n      snDiff === 0 &&\n      chunkMeta.id > 1 &&\n      chunkMeta.id === lastFrag?.stats.chunkCount;\n    const contiguous =\n      !trackSwitch &&\n      (snDiff === 1 ||\n        (snDiff === 0 && (partDiff === 1 || (progressive && partDiff <= 0))));\n    const now = self.performance.now();\n\n    if (trackSwitch || snDiff || frag.stats.parsing.start === 0) {\n      frag.stats.parsing.start = now;\n    }\n    if (part && (partDiff || !contiguous)) {\n      part.stats.parsing.start = now;\n    }\n    const initSegmentChange = !(\n      lastFrag && frag.initSegment?.url === lastFrag.initSegment?.url\n    );\n    const state = new TransmuxState(\n      discontinuity,\n      contiguous,\n      accurateTimeOffset,\n      trackSwitch,\n      timeOffset,\n      initSegmentChange,\n    );\n    if (!contiguous || discontinuity || initSegmentChange) {\n      logger.log(`[transmuxer-interface, ${frag.type}]: Starting new transmux session for sn: ${chunkMeta.sn} p: ${chunkMeta.part} level: ${chunkMeta.level} id: ${chunkMeta.id}\n        discontinuity: ${discontinuity}\n        trackSwitch: ${trackSwitch}\n        contiguous: ${contiguous}\n        accurateTimeOffset: ${accurateTimeOffset}\n        timeOffset: ${timeOffset}\n        initSegmentChange: ${initSegmentChange}`);\n      const config = new TransmuxConfig(\n        audioCodec,\n        videoCodec,\n        initSegmentData,\n        duration,\n        defaultInitPTS,\n      );\n      this.configureTransmuxer(config);\n    }\n\n    this.frag = frag;\n    this.part = part;\n\n    // Frags with sn of 'initSegment' are not transmuxed\n    if (this.workerContext) {\n      // post fragment payload as transferable objects for ArrayBuffer (no copy)\n      this.workerContext.worker.postMessage(\n        {\n          cmd: 'demux',\n          data,\n          decryptdata,\n          chunkMeta,\n          state,\n        },\n        data instanceof ArrayBuffer ? [data] : [],\n      );\n    } else if (transmuxer) {\n      const transmuxResult = transmuxer.push(\n        data,\n        decryptdata,\n        chunkMeta,\n        state,\n      );\n      if (isPromise(transmuxResult)) {\n        transmuxer.async = true;\n        transmuxResult\n          .then((data) => {\n            this.handleTransmuxComplete(data);\n          })\n          .catch((error) => {\n            this.transmuxerError(\n              error,\n              chunkMeta,\n              'transmuxer-interface push error',\n            );\n          });\n      } else {\n        transmuxer.async = false;\n        this.handleTransmuxComplete(transmuxResult as TransmuxerResult);\n      }\n    }\n  }\n\n  flush(chunkMeta: ChunkMetadata) {\n    chunkMeta.transmuxing.start = self.performance.now();\n    const { transmuxer } = this;\n    if (this.workerContext) {\n      1;\n      this.workerContext.worker.postMessage({\n        cmd: 'flush',\n        chunkMeta,\n      });\n    } else if (transmuxer) {\n      let transmuxResult = transmuxer.flush(chunkMeta);\n      const asyncFlush = isPromise(transmuxResult);\n      if (asyncFlush || transmuxer.async) {\n        if (!isPromise(transmuxResult)) {\n          transmuxResult = Promise.resolve(transmuxResult);\n        }\n        transmuxResult\n          .then((data) => {\n            this.handleFlushResult(data, chunkMeta);\n          })\n          .catch((error) => {\n            this.transmuxerError(\n              error,\n              chunkMeta,\n              'transmuxer-interface flush error',\n            );\n          });\n      } else {\n        this.handleFlushResult(\n          transmuxResult as Array<TransmuxerResult>,\n          chunkMeta,\n        );\n      }\n    }\n  }\n\n  private transmuxerError(\n    error: Error,\n    chunkMeta: ChunkMetadata,\n    reason: string,\n  ) {\n    if (!this.hls) {\n      return;\n    }\n    this.error = error;\n    this.hls.trigger(Events.ERROR, {\n      type: ErrorTypes.MEDIA_ERROR,\n      details: ErrorDetails.FRAG_PARSING_ERROR,\n      chunkMeta,\n      frag: this.frag || undefined,\n      fatal: false,\n      error,\n      err: error,\n      reason,\n    });\n  }\n\n  private handleFlushResult(\n    results: Array<TransmuxerResult>,\n    chunkMeta: ChunkMetadata,\n  ) {\n    results.forEach((result) => {\n      this.handleTransmuxComplete(result);\n    });\n    this.onFlush(chunkMeta);\n  }\n\n  private onWorkerMessage(\n    event: MessageEvent<{ event: string; data?: any } | null>,\n  ) {\n    const data = event.data;\n    if (!data?.event) {\n      logger.warn(\n        `worker message received with no ${data ? 'event name' : 'data'}`,\n      );\n      return;\n    }\n    const hls = this.hls;\n    if (!this.hls) {\n      return;\n    }\n    switch (data.event) {\n      case 'init': {\n        const objectURL = this.workerContext?.objectURL;\n        if (objectURL) {\n          // revoke the Object URL that was used to create transmuxer worker, so as not to leak it\n          self.URL.revokeObjectURL(objectURL);\n        }\n        break;\n      }\n\n      case 'transmuxComplete': {\n        this.handleTransmuxComplete(data.data);\n        break;\n      }\n\n      case 'flush': {\n        this.onFlush(data.data);\n        break;\n      }\n\n      // pass logs from the worker thread to the main logger\n      case 'workerLog':\n        if (logger[data.data.logType]) {\n          logger[data.data.logType](data.data.message);\n        }\n        break;\n\n      default: {\n        data.data = data.data || {};\n        data.data.frag = this.frag;\n        data.data.id = this.id;\n        hls.trigger(data.event as keyof HlsListeners, data.data);\n        break;\n      }\n    }\n  }\n\n  private configureTransmuxer(config: TransmuxConfig) {\n    const { transmuxer } = this;\n    if (this.workerContext) {\n      this.workerContext.worker.postMessage({\n        cmd: 'configure',\n        config,\n      });\n    } else if (transmuxer) {\n      transmuxer.configure(config);\n    }\n  }\n\n  private handleTransmuxComplete(result: TransmuxerResult) {\n    result.chunkMeta.transmuxing.end = self.performance.now();\n    this.onTransmuxComplete(result);\n  }\n}\n", "import type { Level } from '../types/level';\nimport type { MediaAttributes, MediaPlaylist } from '../types/media-playlist';\n\nexport function subtitleOptionsIdentical(\n  trackList1: MediaPlaylist[] | Level[],\n  trackList2: MediaPlaylist[],\n): boolean {\n  if (trackList1.length !== trackList2.length) {\n    return false;\n  }\n  for (let i = 0; i < trackList1.length; i++) {\n    if (\n      !mediaAttributesIdentical(\n        trackList1[i].attrs as MediaAttributes,\n        trackList2[i].attrs,\n      )\n    ) {\n      return false;\n    }\n  }\n  return true;\n}\n\nexport function mediaAttributesIdentical(\n  attrs1: MediaAttributes,\n  attrs2: MediaAttributes,\n  customAttributes?: string[],\n): boolean {\n  // Media options with the same rendition ID must be bit identical\n  const stableRenditionId = attrs1['STABLE-RENDITION-ID'];\n  if (stableRenditionId && !customAttributes) {\n    return stableRenditionId === attrs2['STABLE-RENDITION-ID'];\n  }\n  // When rendition ID is not present, compare attributes\n  return !(\n    customAttributes || [\n      'LANGUAGE',\n      'NAME',\n      'CHARACTERISTICS',\n      'AUTOSELECT',\n      'DEFAULT',\n      'FORCED',\n      'ASSOC-LANGUAGE',\n    ]\n  ).some(\n    (subtitleAttribute) =>\n      attrs1[subtitleAttribute] !== attrs2[subtitleAttribute],\n  );\n}\n\nexport function subtitleTrackMatchesTextTrack(\n  subtitleTrack: Pick<MediaPlaylist, 'name' | 'lang' | 'attrs'>,\n  textTrack: TextTrack,\n) {\n  return (\n    textTrack.label.toLowerCase() === subtitleTrack.name.toLowerCase() &&\n    (!textTrack.language ||\n      textTrack.language.toLowerCase() ===\n        (subtitleTrack.lang || '').toLowerCase())\n  );\n}\n", "import BaseStreamController, { State } from './base-stream-controller';\nimport { Events } from '../events';\nimport { Bufferable, BufferHelper } from '../utils/buffer-helper';\nimport { FragmentState } from './fragment-tracker';\nimport { Level } from '../types/level';\nimport { PlaylistContextType, PlaylistLevelType } from '../types/loader';\nimport { Fragment, ElementaryStreamTypes, Part } from '../loader/fragment';\nimport ChunkCache from '../demux/chunk-cache';\nimport TransmuxerInterface from '../demux/transmuxer-interface';\nimport { ChunkMetadata } from '../types/transmuxer';\nimport { fragmentWithinToleranceTest } from './fragment-finders';\nimport { alignMediaPlaylistByPDT } from '../utils/discontinuities';\nimport { mediaAttributesIdentical } from '../utils/media-option-attributes';\nimport { ErrorDetails } from '../errors';\nimport type { NetworkComponentAPI } from '../types/component-api';\nimport type Hls from '../hls';\nimport type { FragmentTracker } from './fragment-tracker';\nimport type KeyLoader from '../loader/key-loader';\nimport type { TransmuxerResult } from '../types/transmuxer';\nimport type { LevelDetails } from '../loader/level-details';\nimport type { TrackSet } from '../types/track';\nimport type {\n  BufferCreatedData,\n  AudioTracksUpdatedData,\n  AudioTrackSwitchingData,\n  LevelLoadedData,\n  TrackLoadedData,\n  BufferAppendingData,\n  BufferFlushedData,\n  InitPTSFoundData,\n  FragLoadedData,\n  FragParsingMetadataData,\n  FragParsingUserdataData,\n  FragBufferedData,\n  ErrorData,\n  BufferFlushingData,\n} from '../types/events';\nimport type { MediaPlaylist } from '../types/media-playlist';\n\nconst TICK_INTERVAL = 100; // how often to tick in ms\n\ntype WaitingForPTSData = {\n  frag: Fragment;\n  part: Part | null;\n  cache: ChunkCache;\n  complete: boolean;\n};\n\nclass AudioStreamController\n  extends BaseStreamController\n  implements NetworkComponentAPI\n{\n  private videoBuffer: Bufferable | null = null;\n  private videoTrackCC: number = -1;\n  private waitingVideoCC: number = -1;\n  private bufferedTrack: MediaPlaylist | null = null;\n  private switchingTrack: MediaPlaylist | null = null;\n  private trackId: number = -1;\n  private waitingData: WaitingForPTSData | null = null;\n  private mainDetails: LevelDetails | null = null;\n  private flushing: boolean = false;\n  private bufferFlushed: boolean = false;\n  private cachedTrackLoadedData: TrackLoadedData | null = null;\n\n  constructor(\n    hls: Hls,\n    fragmentTracker: FragmentTracker,\n    keyLoader: KeyLoader,\n  ) {\n    super(\n      hls,\n      fragmentTracker,\n      keyLoader,\n      '[audio-stream-controller]',\n      PlaylistLevelType.AUDIO,\n    );\n    this._registerListeners();\n  }\n\n  protected onHandlerDestroying() {\n    this._unregisterListeners();\n    super.onHandlerDestroying();\n    this.mainDetails = null;\n    this.bufferedTrack = null;\n    this.switchingTrack = null;\n  }\n\n  private _registerListeners() {\n    const { hls } = this;\n    hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n    hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n    hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);\n    hls.on(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);\n    hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);\n    hls.on(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);\n    hls.on(Events.ERROR, this.onError, this);\n    hls.on(Events.BUFFER_RESET, this.onBufferReset, this);\n    hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);\n    hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);\n    hls.on(Events.BUFFER_FLUSHED, this.onBufferFlushed, this);\n    hls.on(Events.INIT_PTS_FOUND, this.onInitPtsFound, this);\n    hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);\n  }\n\n  private _unregisterListeners() {\n    const { hls } = this;\n    hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n    hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n    hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);\n    hls.off(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);\n    hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);\n    hls.off(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);\n    hls.off(Events.ERROR, this.onError, this);\n    hls.off(Events.BUFFER_RESET, this.onBufferReset, this);\n    hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);\n    hls.off(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);\n    hls.off(Events.BUFFER_FLUSHED, this.onBufferFlushed, this);\n    hls.off(Events.INIT_PTS_FOUND, this.onInitPtsFound, this);\n    hls.off(Events.FRAG_BUFFERED, this.onFragBuffered, this);\n  }\n\n  // INIT_PTS_FOUND is triggered when the video track parsed in the stream-controller has a new PTS value\n  onInitPtsFound(\n    event: Events.INIT_PTS_FOUND,\n    { frag, id, initPTS, timescale }: InitPTSFoundData,\n  ) {\n    // Always update the new INIT PTS\n    // Can change due level switch\n    if (id === 'main') {\n      const cc = frag.cc;\n      this.initPTS[frag.cc] = { baseTime: initPTS, timescale };\n      this.log(`InitPTS for cc: ${cc} found from main: ${initPTS}`);\n      this.videoTrackCC = cc;\n      // If we are waiting, tick immediately to unblock audio fragment transmuxing\n      if (this.state === State.WAITING_INIT_PTS) {\n        this.tick();\n      }\n    }\n  }\n\n  startLoad(startPosition: number) {\n    if (!this.levels) {\n      this.startPosition = startPosition;\n      this.state = State.STOPPED;\n      return;\n    }\n    const lastCurrentTime = this.lastCurrentTime;\n    this.stopLoad();\n    this.setInterval(TICK_INTERVAL);\n    if (lastCurrentTime > 0 && startPosition === -1) {\n      this.log(\n        `Override startPosition with lastCurrentTime @${lastCurrentTime.toFixed(\n          3,\n        )}`,\n      );\n      startPosition = lastCurrentTime;\n      this.state = State.IDLE;\n    } else {\n      this.loadedmetadata = false;\n      this.state = State.WAITING_TRACK;\n    }\n    this.nextLoadPosition =\n      this.startPosition =\n      this.lastCurrentTime =\n        startPosition;\n\n    this.tick();\n  }\n\n  doTick() {\n    switch (this.state) {\n      case State.IDLE:\n        this.doTickIdle();\n        break;\n      case State.WAITING_TRACK: {\n        const { levels, trackId } = this;\n        const details = levels?.[trackId]?.details;\n        if (details) {\n          if (this.waitForCdnTuneIn(details)) {\n            break;\n          }\n          this.state = State.WAITING_INIT_PTS;\n        }\n        break;\n      }\n      case State.FRAG_LOADING_WAITING_RETRY: {\n        const now = performance.now();\n        const retryDate = this.retryDate;\n        // if current time is gt than retryDate, or if media seeking let's switch to IDLE state to retry loading\n        if (!retryDate || now >= retryDate || this.media?.seeking) {\n          const { levels, trackId } = this;\n          this.log('RetryDate reached, switch back to IDLE state');\n          this.resetStartWhenNotLoaded(levels?.[trackId] || null);\n          this.state = State.IDLE;\n        }\n        break;\n      }\n      case State.WAITING_INIT_PTS: {\n        // Ensure we don't get stuck in the WAITING_INIT_PTS state if the waiting frag CC doesn't match any initPTS\n        const waitingData = this.waitingData;\n        if (waitingData) {\n          const { frag, part, cache, complete } = waitingData;\n          if (this.initPTS[frag.cc] !== undefined) {\n            this.waitingData = null;\n            this.waitingVideoCC = -1;\n            this.state = State.FRAG_LOADING;\n            const payload = cache.flush();\n            const data: FragLoadedData = {\n              frag,\n              part,\n              payload,\n              networkDetails: null,\n            };\n            this._handleFragmentLoadProgress(data);\n            if (complete) {\n              super._handleFragmentLoadComplete(data);\n            }\n          } else if (this.videoTrackCC !== this.waitingVideoCC) {\n            // Drop waiting fragment if videoTrackCC has changed since waitingFragment was set and initPTS was not found\n            this.log(\n              `Waiting fragment cc (${frag.cc}) cancelled because video is at cc ${this.videoTrackCC}`,\n            );\n            this.clearWaitingFragment();\n          } else {\n            // Drop waiting fragment if an earlier fragment is needed\n            const pos = this.getLoadPosition();\n            const bufferInfo = BufferHelper.bufferInfo(\n              this.mediaBuffer,\n              pos,\n              this.config.maxBufferHole,\n            );\n            const waitingFragmentAtPosition = fragmentWithinToleranceTest(\n              bufferInfo.end,\n              this.config.maxFragLookUpTolerance,\n              frag,\n            );\n            if (waitingFragmentAtPosition < 0) {\n              this.log(\n                `Waiting fragment cc (${frag.cc}) @ ${frag.start} cancelled because another fragment at ${bufferInfo.end} is needed`,\n              );\n              this.clearWaitingFragment();\n            }\n          }\n        } else {\n          this.state = State.IDLE;\n        }\n      }\n    }\n\n    this.onTickEnd();\n  }\n\n  clearWaitingFragment() {\n    const waitingData = this.waitingData;\n    if (waitingData) {\n      this.fragmentTracker.removeFragment(waitingData.frag);\n      this.waitingData = null;\n      this.waitingVideoCC = -1;\n      this.state = State.IDLE;\n    }\n  }\n\n  protected resetLoadingState() {\n    this.clearWaitingFragment();\n    super.resetLoadingState();\n  }\n\n  protected onTickEnd() {\n    const { media } = this;\n    if (!media?.readyState) {\n      // Exit early if we don't have media or if the media hasn't buffered anything yet (readyState 0)\n      return;\n    }\n\n    this.lastCurrentTime = media.currentTime;\n  }\n\n  private doTickIdle() {\n    const { hls, levels, media, trackId } = this;\n    const config = hls.config;\n\n    // 1. if video not attached AND\n    //    start fragment already requested OR start frag prefetch not enabled\n    // 2. if tracks or track not loaded and selected\n    // then exit loop\n    // => if media not attached but start frag prefetch is enabled and start frag not requested yet, we will not exit loop\n    if (\n      (!media && (this.startFragRequested || !config.startFragPrefetch)) ||\n      !levels?.[trackId]\n    ) {\n      return;\n    }\n\n    const levelInfo = levels[trackId];\n\n    const trackDetails = levelInfo.details;\n    if (\n      !trackDetails ||\n      (trackDetails.live && this.levelLastLoaded !== levelInfo) ||\n      this.waitForCdnTuneIn(trackDetails)\n    ) {\n      this.state = State.WAITING_TRACK;\n      return;\n    }\n\n    const bufferable = this.mediaBuffer ? this.mediaBuffer : this.media;\n    if (this.bufferFlushed && bufferable) {\n      this.bufferFlushed = false;\n      this.afterBufferFlushed(\n        bufferable,\n        ElementaryStreamTypes.AUDIO,\n        PlaylistLevelType.AUDIO,\n      );\n    }\n\n    const bufferInfo = this.getFwdBufferInfo(\n      bufferable,\n      PlaylistLevelType.AUDIO,\n    );\n    if (bufferInfo === null) {\n      return;\n    }\n    const { bufferedTrack, switchingTrack } = this;\n\n    if (!switchingTrack && this._streamEnded(bufferInfo, trackDetails)) {\n      hls.trigger(Events.BUFFER_EOS, { type: 'audio' });\n      this.state = State.ENDED;\n      return;\n    }\n\n    const mainBufferInfo = this.getFwdBufferInfo(\n      this.videoBuffer ? this.videoBuffer : this.media,\n      PlaylistLevelType.MAIN,\n    );\n    const bufferLen = bufferInfo.len;\n    const maxBufLen = this.getMaxBufferLength(mainBufferInfo?.len);\n\n    const fragments = trackDetails.fragments;\n    const start = fragments[0].start;\n    let targetBufferTime = this.flushing\n      ? this.getLoadPosition()\n      : bufferInfo.end;\n\n    if (switchingTrack && media) {\n      const pos = this.getLoadPosition();\n      // STABLE\n      if (\n        bufferedTrack &&\n        !mediaAttributesIdentical(switchingTrack.attrs, bufferedTrack.attrs)\n      ) {\n        targetBufferTime = pos;\n      }\n      // if currentTime (pos) is less than alt audio playlist start time, it means that alt audio is ahead of currentTime\n      if (trackDetails.PTSKnown && pos < start) {\n        // if everything is buffered from pos to start or if audio buffer upfront, let's seek to start\n        if (bufferInfo.end > start || bufferInfo.nextStart) {\n          this.log(\n            'Alt audio track ahead of main track, seek to start of alt audio track',\n          );\n          media.currentTime = start + 0.05;\n        }\n      }\n    }\n\n    // if buffer length is less than maxBufLen, or near the end, find a fragment to load\n    if (\n      bufferLen >= maxBufLen &&\n      !switchingTrack &&\n      targetBufferTime < fragments[fragments.length - 1].start\n    ) {\n      return;\n    }\n\n    let frag = this.getNextFragment(targetBufferTime, trackDetails);\n    let atGap = false;\n    // Avoid loop loading by using nextLoadPosition set for backtracking and skipping consecutive GAP tags\n    if (frag && this.isLoopLoading(frag, targetBufferTime)) {\n      atGap = !!frag.gap;\n      frag = this.getNextFragmentLoopLoading(\n        frag,\n        trackDetails,\n        bufferInfo,\n        PlaylistLevelType.MAIN,\n        maxBufLen,\n      );\n    }\n    if (!frag) {\n      this.bufferFlushed = true;\n      return;\n    }\n\n    // Buffer audio up to one target duration ahead of main buffer\n    const atBufferSyncLimit =\n      mainBufferInfo &&\n      frag.start > mainBufferInfo.end + trackDetails.targetduration;\n    if (\n      atBufferSyncLimit ||\n      // Or wait for main buffer after buffing some audio\n      (!mainBufferInfo?.len && bufferInfo.len)\n    ) {\n      // Check fragment-tracker for main fragments since GAP segments do not show up in bufferInfo\n      const mainFrag = this.getAppendedFrag(frag.start, PlaylistLevelType.MAIN);\n      if (mainFrag === null) {\n        return;\n      }\n      // Bridge gaps in main buffer\n      atGap ||=\n        !!mainFrag.gap || (!!atBufferSyncLimit && mainBufferInfo.len === 0);\n      if (\n        (atBufferSyncLimit && !atGap) ||\n        (atGap && bufferInfo.nextStart && bufferInfo.nextStart < mainFrag.end)\n      ) {\n        return;\n      }\n    }\n\n    this.loadFragment(frag, levelInfo, targetBufferTime);\n  }\n\n  protected getMaxBufferLength(mainBufferLength?: number): number {\n    const maxConfigBuffer = super.getMaxBufferLength();\n    if (!mainBufferLength) {\n      return maxConfigBuffer;\n    }\n    return Math.min(\n      Math.max(maxConfigBuffer, mainBufferLength),\n      this.config.maxMaxBufferLength,\n    );\n  }\n\n  onMediaDetaching() {\n    this.videoBuffer = null;\n    this.bufferFlushed = this.flushing = false;\n    super.onMediaDetaching();\n  }\n\n  onAudioTracksUpdated(\n    event: Events.AUDIO_TRACKS_UPDATED,\n    { audioTracks }: AudioTracksUpdatedData,\n  ) {\n    // Reset tranxmuxer is essential for large context switches (Content Steering)\n    this.resetTransmuxer();\n    this.levels = audioTracks.map((mediaPlaylist) => new Level(mediaPlaylist));\n  }\n\n  onAudioTrackSwitching(\n    event: Events.AUDIO_TRACK_SWITCHING,\n    data: AudioTrackSwitchingData,\n  ) {\n    // if any URL found on new audio track, it is an alternate audio track\n    const altAudio = !!data.url;\n    this.trackId = data.id;\n    const { fragCurrent } = this;\n\n    if (fragCurrent) {\n      fragCurrent.abortRequests();\n      this.removeUnbufferedFrags(fragCurrent.start);\n    }\n    this.resetLoadingState();\n    // destroy useless transmuxer when switching audio to main\n    if (!altAudio) {\n      this.resetTransmuxer();\n    } else {\n      // switching to audio track, start timer if not already started\n      this.setInterval(TICK_INTERVAL);\n    }\n\n    // should we switch tracks ?\n    if (altAudio) {\n      this.switchingTrack = data;\n      // main audio track are handled by stream-controller, just do something if switching to alt audio track\n      this.state = State.IDLE;\n      this.flushAudioIfNeeded(data);\n    } else {\n      this.switchingTrack = null;\n      this.bufferedTrack = data;\n      this.state = State.STOPPED;\n    }\n    this.tick();\n  }\n\n  onManifestLoading() {\n    this.fragmentTracker.removeAllFragments();\n    this.startPosition = this.lastCurrentTime = 0;\n    this.bufferFlushed = this.flushing = false;\n    this.levels =\n      this.mainDetails =\n      this.waitingData =\n      this.bufferedTrack =\n      this.cachedTrackLoadedData =\n      this.switchingTrack =\n        null;\n    this.startFragRequested = false;\n    this.trackId = this.videoTrackCC = this.waitingVideoCC = -1;\n  }\n\n  onLevelLoaded(event: Events.LEVEL_LOADED, data: LevelLoadedData) {\n    this.mainDetails = data.details;\n    if (this.cachedTrackLoadedData !== null) {\n      this.hls.trigger(Events.AUDIO_TRACK_LOADED, this.cachedTrackLoadedData);\n      this.cachedTrackLoadedData = null;\n    }\n  }\n\n  onAudioTrackLoaded(event: Events.AUDIO_TRACK_LOADED, data: TrackLoadedData) {\n    if (this.mainDetails == null) {\n      this.cachedTrackLoadedData = data;\n      return;\n    }\n    const { levels } = this;\n    const { details: newDetails, id: trackId } = data;\n    if (!levels) {\n      this.warn(`Audio tracks were reset while loading level ${trackId}`);\n      return;\n    }\n    this.log(\n      `Audio track ${trackId} loaded [${newDetails.startSN},${\n        newDetails.endSN\n      }]${\n        newDetails.lastPartSn\n          ? `[part-${newDetails.lastPartSn}-${newDetails.lastPartIndex}]`\n          : ''\n      },duration:${newDetails.totalduration}`,\n    );\n\n    const track = levels[trackId];\n    let sliding = 0;\n    if (newDetails.live || track.details?.live) {\n      this.checkLiveUpdate(newDetails);\n      const mainDetails = this.mainDetails;\n      if (newDetails.deltaUpdateFailed || !mainDetails) {\n        return;\n      }\n      if (\n        !track.details &&\n        newDetails.hasProgramDateTime &&\n        mainDetails.hasProgramDateTime\n      ) {\n        // Make sure our audio rendition is aligned with the \"main\" rendition, using\n        // pdt as our reference times.\n        alignMediaPlaylistByPDT(newDetails, mainDetails);\n        sliding = newDetails.fragments[0].start;\n      } else {\n        sliding = this.alignPlaylists(\n          newDetails,\n          track.details,\n          this.levelLastLoaded?.details,\n        );\n      }\n    }\n    track.details = newDetails;\n    this.levelLastLoaded = track;\n\n    // compute start position if we are aligned with the main playlist\n    if (!this.startFragRequested && (this.mainDetails || !newDetails.live)) {\n      this.setStartPosition(this.mainDetails || newDetails, sliding);\n    }\n    // only switch back to IDLE state if we were waiting for track to start downloading a new fragment\n    if (\n      this.state === State.WAITING_TRACK &&\n      !this.waitForCdnTuneIn(newDetails)\n    ) {\n      this.state = State.IDLE;\n    }\n\n    // trigger handler right now\n    this.tick();\n  }\n\n  _handleFragmentLoadProgress(data: FragLoadedData) {\n    const { frag, part, payload } = data;\n    const { config, trackId, levels } = this;\n    if (!levels) {\n      this.warn(\n        `Audio tracks were reset while fragment load was in progress. Fragment ${frag.sn} of level ${frag.level} will not be buffered`,\n      );\n      return;\n    }\n\n    const track = levels[trackId] as Level;\n    if (!track) {\n      this.warn('Audio track is undefined on fragment load progress');\n      return;\n    }\n    const details = track.details as LevelDetails;\n    if (!details) {\n      this.warn('Audio track details undefined on fragment load progress');\n      this.removeUnbufferedFrags(frag.start);\n      return;\n    }\n    const audioCodec =\n      config.defaultAudioCodec || track.audioCodec || 'mp4a.40.2';\n\n    let transmuxer = this.transmuxer;\n    if (!transmuxer) {\n      transmuxer = this.transmuxer = new TransmuxerInterface(\n        this.hls,\n        PlaylistLevelType.AUDIO,\n        this._handleTransmuxComplete.bind(this),\n        this._handleTransmuxerFlush.bind(this),\n      );\n    }\n\n    // Check if we have video initPTS\n    // If not we need to wait for it\n    const initPTS = this.initPTS[frag.cc];\n    const initSegmentData = frag.initSegment?.data;\n    if (initPTS !== undefined) {\n      // this.log(`Transmuxing ${sn} of [${details.startSN} ,${details.endSN}],track ${trackId}`);\n      // time Offset is accurate if level PTS is known, or if playlist is not sliding (not live)\n      const accurateTimeOffset = false; // details.PTSKnown || !details.live;\n      const partIndex = part ? part.index : -1;\n      const partial = partIndex !== -1;\n      const chunkMeta = new ChunkMetadata(\n        frag.level,\n        frag.sn as number,\n        frag.stats.chunkCount,\n        payload.byteLength,\n        partIndex,\n        partial,\n      );\n      transmuxer.push(\n        payload,\n        initSegmentData,\n        audioCodec,\n        '',\n        frag,\n        part,\n        details.totalduration,\n        accurateTimeOffset,\n        chunkMeta,\n        initPTS,\n      );\n    } else {\n      this.log(\n        `Unknown video PTS for cc ${frag.cc}, waiting for video PTS before demuxing audio frag ${frag.sn} of [${details.startSN} ,${details.endSN}],track ${trackId}`,\n      );\n      const { cache } = (this.waitingData = this.waitingData || {\n        frag,\n        part,\n        cache: new ChunkCache(),\n        complete: false,\n      });\n      cache.push(new Uint8Array(payload));\n      this.waitingVideoCC = this.videoTrackCC;\n      this.state = State.WAITING_INIT_PTS;\n    }\n  }\n\n  protected _handleFragmentLoadComplete(fragLoadedData: FragLoadedData) {\n    if (this.waitingData) {\n      this.waitingData.complete = true;\n      return;\n    }\n    super._handleFragmentLoadComplete(fragLoadedData);\n  }\n\n  onBufferReset(/* event: Events.BUFFER_RESET */) {\n    // reset reference to sourcebuffers\n    this.mediaBuffer = this.videoBuffer = null;\n    this.loadedmetadata = false;\n  }\n\n  onBufferCreated(event: Events.BUFFER_CREATED, data: BufferCreatedData) {\n    const audioTrack = data.tracks.audio;\n    if (audioTrack) {\n      this.mediaBuffer = audioTrack.buffer || null;\n    }\n    if (data.tracks.video) {\n      this.videoBuffer = data.tracks.video.buffer || null;\n    }\n  }\n\n  onFragBuffered(event: Events.FRAG_BUFFERED, data: FragBufferedData) {\n    const { frag, part } = data;\n    if (frag.type !== PlaylistLevelType.AUDIO) {\n      if (!this.loadedmetadata && frag.type === PlaylistLevelType.MAIN) {\n        const bufferable = this.videoBuffer || this.media;\n        if (bufferable) {\n          const bufferedTimeRanges = BufferHelper.getBuffered(bufferable);\n          if (bufferedTimeRanges.length) {\n            this.loadedmetadata = true;\n          }\n        }\n      }\n      return;\n    }\n    if (this.fragContextChanged(frag)) {\n      // If a level switch was requested while a fragment was buffering, it will emit the FRAG_BUFFERED event upon completion\n      // Avoid setting state back to IDLE or concluding the audio switch; otherwise, the switched-to track will not buffer\n      this.warn(\n        `Fragment ${frag.sn}${part ? ' p: ' + part.index : ''} of level ${\n          frag.level\n        } finished buffering, but was aborted. state: ${\n          this.state\n        }, audioSwitch: ${\n          this.switchingTrack ? this.switchingTrack.name : 'false'\n        }`,\n      );\n      return;\n    }\n    if (frag.sn !== 'initSegment') {\n      this.fragPrevious = frag;\n      const track = this.switchingTrack;\n      if (track) {\n        this.bufferedTrack = track;\n        this.switchingTrack = null;\n        this.hls.trigger(Events.AUDIO_TRACK_SWITCHED, { ...track });\n      }\n    }\n    this.fragBufferedComplete(frag, part);\n  }\n\n  private onError(event: Events.ERROR, data: ErrorData) {\n    if (data.fatal) {\n      this.state = State.ERROR;\n      return;\n    }\n    switch (data.details) {\n      case ErrorDetails.FRAG_GAP:\n      case ErrorDetails.FRAG_PARSING_ERROR:\n      case ErrorDetails.FRAG_DECRYPT_ERROR:\n      case ErrorDetails.FRAG_LOAD_ERROR:\n      case ErrorDetails.FRAG_LOAD_TIMEOUT:\n      case ErrorDetails.KEY_LOAD_ERROR:\n      case ErrorDetails.KEY_LOAD_TIMEOUT:\n        this.onFragmentOrKeyLoadError(PlaylistLevelType.AUDIO, data);\n        break;\n      case ErrorDetails.AUDIO_TRACK_LOAD_ERROR:\n      case ErrorDetails.AUDIO_TRACK_LOAD_TIMEOUT:\n      case ErrorDetails.LEVEL_PARSING_ERROR:\n        // in case of non fatal error while loading track, if not retrying to load track, switch back to IDLE\n        if (\n          !data.levelRetry &&\n          this.state === State.WAITING_TRACK &&\n          data.context?.type === PlaylistContextType.AUDIO_TRACK\n        ) {\n          this.state = State.IDLE;\n        }\n        break;\n      case ErrorDetails.BUFFER_APPEND_ERROR:\n      case ErrorDetails.BUFFER_FULL_ERROR:\n        if (!data.parent || data.parent !== 'audio') {\n          return;\n        }\n        if (data.details === ErrorDetails.BUFFER_APPEND_ERROR) {\n          this.resetLoadingState();\n          return;\n        }\n        if (this.reduceLengthAndFlushBuffer(data)) {\n          this.bufferedTrack = null;\n          super.flushMainBuffer(0, Number.POSITIVE_INFINITY, 'audio');\n        }\n        break;\n      case ErrorDetails.INTERNAL_EXCEPTION:\n        this.recoverWorkerError(data);\n        break;\n      default:\n        break;\n    }\n  }\n\n  private onBufferFlushing(\n    event: Events.BUFFER_FLUSHING,\n    { type }: BufferFlushingData,\n  ) {\n    if (type !== ElementaryStreamTypes.VIDEO) {\n      this.flushing = true;\n    }\n  }\n\n  private onBufferFlushed(\n    event: Events.BUFFER_FLUSHED,\n    { type }: BufferFlushedData,\n  ) {\n    if (type !== ElementaryStreamTypes.VIDEO) {\n      this.flushing = false;\n      this.bufferFlushed = true;\n      if (this.state === State.ENDED) {\n        this.state = State.IDLE;\n      }\n      const mediaBuffer = this.mediaBuffer || this.media;\n      if (mediaBuffer) {\n        this.afterBufferFlushed(mediaBuffer, type, PlaylistLevelType.AUDIO);\n        this.tick();\n      }\n    }\n  }\n\n  private _handleTransmuxComplete(transmuxResult: TransmuxerResult) {\n    const id = 'audio';\n    const { hls } = this;\n    const { remuxResult, chunkMeta } = transmuxResult;\n\n    const context = this.getCurrentContext(chunkMeta);\n    if (!context) {\n      this.resetWhenMissingContext(chunkMeta);\n      return;\n    }\n    const { frag, part, level } = context;\n    const { details } = level;\n    const { audio, text, id3, initSegment } = remuxResult;\n\n    // Check if the current fragment has been aborted. We check this by first seeing if we're still playing the current level.\n    // If we are, subsequently check if the currently loading fragment (fragCurrent) has changed.\n    if (this.fragContextChanged(frag) || !details) {\n      this.fragmentTracker.removeFragment(frag);\n      return;\n    }\n\n    this.state = State.PARSING;\n    if (this.switchingTrack && audio) {\n      this.completeAudioSwitch(this.switchingTrack);\n    }\n\n    if (initSegment?.tracks) {\n      const mapFragment = frag.initSegment || frag;\n      this._bufferInitSegment(\n        level,\n        initSegment.tracks,\n        mapFragment,\n        chunkMeta,\n      );\n      hls.trigger(Events.FRAG_PARSING_INIT_SEGMENT, {\n        frag: mapFragment,\n        id,\n        tracks: initSegment.tracks,\n      });\n      // Only flush audio from old audio tracks when PTS is known on new audio track\n    }\n    if (audio) {\n      const { startPTS, endPTS, startDTS, endDTS } = audio;\n      if (part) {\n        part.elementaryStreams[ElementaryStreamTypes.AUDIO] = {\n          startPTS,\n          endPTS,\n          startDTS,\n          endDTS,\n        };\n      }\n      frag.setElementaryStreamInfo(\n        ElementaryStreamTypes.AUDIO,\n        startPTS,\n        endPTS,\n        startDTS,\n        endDTS,\n      );\n      this.bufferFragmentData(audio, frag, part, chunkMeta);\n    }\n\n    if (id3?.samples?.length) {\n      const emittedID3: FragParsingMetadataData = Object.assign(\n        {\n          id,\n          frag,\n          details,\n        },\n        id3,\n      );\n      hls.trigger(Events.FRAG_PARSING_METADATA, emittedID3);\n    }\n    if (text) {\n      const emittedText: FragParsingUserdataData = Object.assign(\n        {\n          id,\n          frag,\n          details,\n        },\n        text,\n      );\n      hls.trigger(Events.FRAG_PARSING_USERDATA, emittedText);\n    }\n  }\n\n  private _bufferInitSegment(\n    currentLevel: Level,\n    tracks: TrackSet,\n    frag: Fragment,\n    chunkMeta: ChunkMetadata,\n  ) {\n    if (this.state !== State.PARSING) {\n      return;\n    }\n    // delete any video track found on audio transmuxer\n    if (tracks.video) {\n      delete tracks.video;\n    }\n\n    // include levelCodec in audio and video tracks\n    const track = tracks.audio;\n    if (!track) {\n      return;\n    }\n\n    track.id = 'audio';\n\n    const variantAudioCodecs = currentLevel.audioCodec;\n    this.log(\n      `Init audio buffer, container:${track.container}, codecs[level/parsed]=[${variantAudioCodecs}/${track.codec}]`,\n    );\n    // SourceBuffer will use track.levelCodec if defined\n    if (variantAudioCodecs && variantAudioCodecs.split(',').length === 1) {\n      track.levelCodec = variantAudioCodecs;\n    }\n    this.hls.trigger(Events.BUFFER_CODECS, tracks);\n    const initSegment = track.initSegment;\n    if (initSegment?.byteLength) {\n      const segment: BufferAppendingData = {\n        type: 'audio',\n        frag,\n        part: null,\n        chunkMeta,\n        parent: frag.type,\n        data: initSegment,\n      };\n      this.hls.trigger(Events.BUFFER_APPENDING, segment);\n    }\n    // trigger handler right now\n    this.tickImmediate();\n  }\n\n  protected loadFragment(\n    frag: Fragment,\n    track: Level,\n    targetBufferTime: number,\n  ) {\n    // only load if fragment is not loaded or if in audio switch\n    const fragState = this.fragmentTracker.getState(frag);\n    this.fragCurrent = frag;\n\n    // we force a frag loading in audio switch as fragment tracker might not have evicted previous frags in case of quick audio switch\n    if (\n      this.switchingTrack ||\n      fragState === FragmentState.NOT_LOADED ||\n      fragState === FragmentState.PARTIAL\n    ) {\n      if (frag.sn === 'initSegment') {\n        this._loadInitSegment(frag, track);\n      } else if (track.details?.live && !this.initPTS[frag.cc]) {\n        this.log(\n          `Waiting for video PTS in continuity counter ${frag.cc} of live stream before loading audio fragment ${frag.sn} of level ${this.trackId}`,\n        );\n        this.state = State.WAITING_INIT_PTS;\n        const mainDetails = this.mainDetails;\n        if (\n          mainDetails &&\n          mainDetails.fragments[0].start !== track.details.fragments[0].start\n        ) {\n          alignMediaPlaylistByPDT(track.details, mainDetails);\n        }\n      } else {\n        this.startFragRequested = true;\n        super.loadFragment(frag, track, targetBufferTime);\n      }\n    } else {\n      this.clearTrackerIfNeeded(frag);\n    }\n  }\n\n  private flushAudioIfNeeded(switchingTrack: MediaPlaylist) {\n    const { media, bufferedTrack } = this;\n    const bufferedAttributes = bufferedTrack?.attrs;\n    const switchAttributes = switchingTrack.attrs;\n    if (\n      media &&\n      bufferedAttributes &&\n      (bufferedAttributes.CHANNELS !== switchAttributes.CHANNELS ||\n        bufferedTrack.name !== switchingTrack.name ||\n        bufferedTrack.lang !== switchingTrack.lang)\n    ) {\n      this.log('Switching audio track : flushing all audio');\n      super.flushMainBuffer(0, Number.POSITIVE_INFINITY, 'audio');\n      this.bufferedTrack = null;\n    }\n  }\n\n  private completeAudioSwitch(switchingTrack: MediaPlaylist) {\n    const { hls } = this;\n    this.flushAudioIfNeeded(switchingTrack);\n    this.bufferedTrack = switchingTrack;\n    this.switchingTrack = null;\n    hls.trigger(Events.AUDIO_TRACK_SWITCHED, { ...switchingTrack });\n  }\n}\nexport default AudioStreamController;\n", "import BasePlaylistController from './base-playlist-controller';\nimport { Events } from '../events';\nimport { ErrorTypes, ErrorDetails } from '../errors';\nimport { PlaylistContextType } from '../types/loader';\nimport { mediaAttributesIdentical } from '../utils/media-option-attributes';\nimport {\n  audioMatchPredicate,\n  findClosestLevelWithAudioGroup,\n  findMatchingOption,\n  matchesOption,\n} from '../utils/rendition-helper';\nimport type Hls from '../hls';\nimport type {\n  AudioSelectionOption,\n  MediaPlaylist,\n} from '../types/media-playlist';\nimport type { HlsUrlParameters } from '../types/level';\nimport type {\n  ManifestParsedData,\n  AudioTracksUpdatedData,\n  ErrorData,\n  LevelLoadingData,\n  AudioTrackLoadedData,\n  LevelSwitchingData,\n} from '../types/events';\n\nclass AudioTrackController extends BasePlaylistController {\n  private tracks: MediaPlaylist[] = [];\n  private groupIds: (string | undefined)[] | null = null;\n  private tracksInGroup: MediaPlaylist[] = [];\n  private trackId: number = -1;\n  private currentTrack: MediaPlaylist | null = null;\n  private selectDefaultTrack: boolean = true;\n\n  constructor(hls: Hls) {\n    super(hls, '[audio-track-controller]');\n    this.registerListeners();\n  }\n\n  private registerListeners() {\n    const { hls } = this;\n    hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    hls.on(Events.MANIFEST_PARSED, this.onManifestParsed, this);\n    hls.on(Events.LEVEL_LOADING, this.onLevelLoading, this);\n    hls.on(Events.LEVEL_SWITCHING, this.onLevelSwitching, this);\n    hls.on(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);\n    hls.on(Events.ERROR, this.onError, this);\n  }\n\n  private unregisterListeners() {\n    const { hls } = this;\n    hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    hls.off(Events.MANIFEST_PARSED, this.onManifestParsed, this);\n    hls.off(Events.LEVEL_LOADING, this.onLevelLoading, this);\n    hls.off(Events.LEVEL_SWITCHING, this.onLevelSwitching, this);\n    hls.off(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);\n    hls.off(Events.ERROR, this.onError, this);\n  }\n\n  public destroy() {\n    this.unregisterListeners();\n    this.tracks.length = 0;\n    this.tracksInGroup.length = 0;\n    this.currentTrack = null;\n    super.destroy();\n  }\n\n  protected onManifestLoading(): void {\n    this.tracks = [];\n    this.tracksInGroup = [];\n    this.groupIds = null;\n    this.currentTrack = null;\n    this.trackId = -1;\n    this.selectDefaultTrack = true;\n  }\n\n  protected onManifestParsed(\n    event: Events.MANIFEST_PARSED,\n    data: ManifestParsedData,\n  ): void {\n    this.tracks = data.audioTracks || [];\n  }\n\n  protected onAudioTrackLoaded(\n    event: Events.AUDIO_TRACK_LOADED,\n    data: AudioTrackLoadedData,\n  ): void {\n    const { id, groupId, details } = data;\n    const trackInActiveGroup = this.tracksInGroup[id];\n\n    if (!trackInActiveGroup || trackInActiveGroup.groupId !== groupId) {\n      this.warn(\n        `Audio track with id:${id} and group:${groupId} not found in active group ${trackInActiveGroup?.groupId}`,\n      );\n      return;\n    }\n\n    const curDetails = trackInActiveGroup.details;\n    trackInActiveGroup.details = data.details;\n    this.log(\n      `Audio track ${id} \"${trackInActiveGroup.name}\" lang:${trackInActiveGroup.lang} group:${groupId} loaded [${details.startSN}-${details.endSN}]`,\n    );\n\n    if (id === this.trackId) {\n      this.playlistLoaded(id, data, curDetails);\n    }\n  }\n\n  protected onLevelLoading(\n    event: Events.LEVEL_LOADING,\n    data: LevelLoadingData,\n  ): void {\n    this.switchLevel(data.level);\n  }\n\n  protected onLevelSwitching(\n    event: Events.LEVEL_SWITCHING,\n    data: LevelSwitchingData,\n  ): void {\n    this.switchLevel(data.level);\n  }\n\n  private switchLevel(levelIndex: number) {\n    const levelInfo = this.hls.levels[levelIndex];\n    if (!levelInfo) {\n      return;\n    }\n    const audioGroups = levelInfo.audioGroups || null;\n    const currentGroups = this.groupIds;\n    let currentTrack = this.currentTrack;\n    if (\n      !audioGroups ||\n      currentGroups?.length !== audioGroups?.length ||\n      audioGroups?.some((groupId) => currentGroups?.indexOf(groupId) === -1)\n    ) {\n      this.groupIds = audioGroups;\n      this.trackId = -1;\n      this.currentTrack = null;\n\n      const audioTracks = this.tracks.filter(\n        (track): boolean =>\n          !audioGroups || audioGroups.indexOf(track.groupId) !== -1,\n      );\n      if (audioTracks.length) {\n        // Disable selectDefaultTrack if there are no default tracks\n        if (\n          this.selectDefaultTrack &&\n          !audioTracks.some((track) => track.default)\n        ) {\n          this.selectDefaultTrack = false;\n        }\n        // track.id should match hls.audioTracks index\n        audioTracks.forEach((track, i) => {\n          track.id = i;\n        });\n      } else if (!currentTrack && !this.tracksInGroup.length) {\n        // Do not dispatch AUDIO_TRACKS_UPDATED when there were and are no tracks\n        return;\n      }\n      this.tracksInGroup = audioTracks;\n\n      // Find preferred track\n      const audioPreference = this.hls.config.audioPreference;\n      if (!currentTrack && audioPreference) {\n        const groupIndex = findMatchingOption(\n          audioPreference,\n          audioTracks,\n          audioMatchPredicate,\n        );\n        if (groupIndex > -1) {\n          currentTrack = audioTracks[groupIndex];\n        } else {\n          const allIndex = findMatchingOption(audioPreference, this.tracks);\n          currentTrack = this.tracks[allIndex];\n        }\n      }\n\n      // Select initial track\n      let trackId = this.findTrackId(currentTrack);\n      if (trackId === -1 && currentTrack) {\n        trackId = this.findTrackId(null);\n      }\n\n      // Dispatch events and load track if needed\n      const audioTracksUpdated: AudioTracksUpdatedData = { audioTracks };\n      this.log(\n        `Updating audio tracks, ${\n          audioTracks.length\n        } track(s) found in group(s): ${audioGroups?.join(',')}`,\n      );\n      this.hls.trigger(Events.AUDIO_TRACKS_UPDATED, audioTracksUpdated);\n\n      const selectedTrackId = this.trackId;\n      if (trackId !== -1 && selectedTrackId === -1) {\n        this.setAudioTrack(trackId);\n      } else if (audioTracks.length && selectedTrackId === -1) {\n        const error = new Error(\n          `No audio track selected for current audio group-ID(s): ${this.groupIds?.join(\n            ',',\n          )} track count: ${audioTracks.length}`,\n        );\n        this.warn(error.message);\n\n        this.hls.trigger(Events.ERROR, {\n          type: ErrorTypes.MEDIA_ERROR,\n          details: ErrorDetails.AUDIO_TRACK_LOAD_ERROR,\n          fatal: true,\n          error,\n        });\n      }\n    } else if (this.shouldReloadPlaylist(currentTrack)) {\n      // Retry playlist loading if no playlist is or has been loaded yet\n      this.setAudioTrack(this.trackId);\n    }\n  }\n\n  protected onError(event: Events.ERROR, data: ErrorData): void {\n    if (data.fatal || !data.context) {\n      return;\n    }\n\n    if (\n      data.context.type === PlaylistContextType.AUDIO_TRACK &&\n      data.context.id === this.trackId &&\n      (!this.groupIds || this.groupIds.indexOf(data.context.groupId) !== -1)\n    ) {\n      this.requestScheduled = -1;\n      this.checkRetry(data);\n    }\n  }\n\n  get allAudioTracks(): MediaPlaylist[] {\n    return this.tracks;\n  }\n\n  get audioTracks(): MediaPlaylist[] {\n    return this.tracksInGroup;\n  }\n\n  get audioTrack(): number {\n    return this.trackId;\n  }\n\n  set audioTrack(newId: number) {\n    // If audio track is selected from API then don't choose from the manifest default track\n    this.selectDefaultTrack = false;\n    this.setAudioTrack(newId);\n  }\n\n  public setAudioOption(\n    audioOption: MediaPlaylist | AudioSelectionOption | undefined,\n  ): MediaPlaylist | null {\n    const hls = this.hls;\n    hls.config.audioPreference = audioOption;\n    if (audioOption) {\n      const allAudioTracks = this.allAudioTracks;\n      this.selectDefaultTrack = false;\n      if (allAudioTracks.length) {\n        // First see if current option matches (no switch op)\n        const currentTrack = this.currentTrack;\n        if (\n          currentTrack &&\n          matchesOption(audioOption, currentTrack, audioMatchPredicate)\n        ) {\n          return currentTrack;\n        }\n        // Find option in available tracks (tracksInGroup)\n        const groupIndex = findMatchingOption(\n          audioOption,\n          this.tracksInGroup,\n          audioMatchPredicate,\n        );\n        if (groupIndex > -1) {\n          const track = this.tracksInGroup[groupIndex];\n          this.setAudioTrack(groupIndex);\n          return track;\n        } else if (currentTrack) {\n          // Find option in nearest level audio group\n          let searchIndex = hls.loadLevel;\n          if (searchIndex === -1) {\n            searchIndex = hls.firstAutoLevel;\n          }\n          const switchIndex = findClosestLevelWithAudioGroup(\n            audioOption,\n            hls.levels,\n            allAudioTracks,\n            searchIndex,\n            audioMatchPredicate,\n          );\n          if (switchIndex === -1) {\n            // could not find matching variant\n            return null;\n          }\n          // and switch level to acheive the audio group switch\n          hls.nextLoadLevel = switchIndex;\n        }\n        if (audioOption.channels || audioOption.audioCodec) {\n          // Could not find a match with codec / channels predicate\n          // Find a match without channels or codec\n          const withoutCodecAndChannelsMatch = findMatchingOption(\n            audioOption,\n            allAudioTracks,\n          );\n          if (withoutCodecAndChannelsMatch > -1) {\n            return allAudioTracks[withoutCodecAndChannelsMatch];\n          }\n        }\n      }\n    }\n    return null;\n  }\n\n  private setAudioTrack(newId: number): void {\n    const tracks = this.tracksInGroup;\n\n    // check if level idx is valid\n    if (newId < 0 || newId >= tracks.length) {\n      this.warn(`Invalid audio track id: ${newId}`);\n      return;\n    }\n\n    // stopping live reloading timer if any\n    this.clearTimer();\n\n    this.selectDefaultTrack = false;\n    const lastTrack = this.currentTrack;\n    const track = tracks[newId];\n    const trackLoaded = track.details && !track.details.live;\n    if (newId === this.trackId && track === lastTrack && trackLoaded) {\n      return;\n    }\n    this.log(\n      `Switching to audio-track ${newId} \"${track.name}\" lang:${track.lang} group:${track.groupId} channels:${track.channels}`,\n    );\n    this.trackId = newId;\n    this.currentTrack = track;\n    this.hls.trigger(Events.AUDIO_TRACK_SWITCHING, { ...track });\n    // Do not reload track unless live\n    if (trackLoaded) {\n      return;\n    }\n    const hlsUrlParameters = this.switchParams(\n      track.url,\n      lastTrack?.details,\n      track.details,\n    );\n    this.loadPlaylist(hlsUrlParameters);\n  }\n\n  private findTrackId(currentTrack: MediaPlaylist | null): number {\n    const audioTracks = this.tracksInGroup;\n    for (let i = 0; i < audioTracks.length; i++) {\n      const track = audioTracks[i];\n      if (this.selectDefaultTrack && !track.default) {\n        continue;\n      }\n      if (\n        !currentTrack ||\n        matchesOption(currentTrack, track, audioMatchPredicate)\n      ) {\n        return i;\n      }\n    }\n    if (currentTrack) {\n      const { name, lang, assocLang, characteristics, audioCodec, channels } =\n        currentTrack;\n      for (let i = 0; i < audioTracks.length; i++) {\n        const track = audioTracks[i];\n        if (\n          matchesOption(\n            { name, lang, assocLang, characteristics, audioCodec, channels },\n            track,\n            audioMatchPredicate,\n          )\n        ) {\n          return i;\n        }\n      }\n      for (let i = 0; i < audioTracks.length; i++) {\n        const track = audioTracks[i];\n        if (\n          mediaAttributesIdentical(currentTrack.attrs, track.attrs, [\n            'LANGUAGE',\n            'ASSOC-LANGUAGE',\n            'CHARACTERISTICS',\n          ])\n        ) {\n          return i;\n        }\n      }\n      for (let i = 0; i < audioTracks.length; i++) {\n        const track = audioTracks[i];\n        if (\n          mediaAttributesIdentical(currentTrack.attrs, track.attrs, [\n            'LANGUAGE',\n          ])\n        ) {\n          return i;\n        }\n      }\n    }\n    return -1;\n  }\n\n  protected loadPlaylist(hlsUrlParameters?: HlsUrlParameters): void {\n    const audioTrack = this.currentTrack;\n    if (this.shouldLoadPlaylist(audioTrack) && audioTrack) {\n      super.loadPlaylist();\n      const id = audioTrack.id;\n      const groupId = audioTrack.groupId as string;\n      let url = audioTrack.url;\n      if (hlsUrlParameters) {\n        try {\n          url = hlsUrlParameters.addDirectives(url);\n        } catch (error) {\n          this.warn(\n            `Could not construct new URL with HLS Delivery Directives: ${error}`,\n          );\n        }\n      }\n      // track not retrieved yet, or live playlist we need to (re)load it\n      this.log(\n        `loading audio-track playlist ${id} \"${audioTrack.name}\" lang:${audioTrack.lang} group:${groupId}`,\n      );\n      this.clearTimer();\n      this.hls.trigger(Events.AUDIO_TRACK_LOADING, {\n        url,\n        id,\n        groupId,\n        deliveryDirectives: hlsUrlParameters || null,\n      });\n    }\n  }\n}\n\nexport default AudioTrackController;\n", "import { Events } from '../events';\nimport { Bufferable, BufferHelper } from '../utils/buffer-helper';\nimport { findFragmentByPTS } from './fragment-finders';\nimport { alignMediaPlaylistByPDT } from '../utils/discontinuities';\nimport { addSliding } from '../utils/level-helper';\nimport { FragmentState } from './fragment-tracker';\nimport BaseStreamController, { State } from './base-stream-controller';\nimport { PlaylistLevelType } from '../types/loader';\nimport { Level } from '../types/level';\nimport { subtitleOptionsIdentical } from '../utils/media-option-attributes';\nimport { ErrorDetails, ErrorTypes } from '../errors';\nimport type { NetworkComponentAPI } from '../types/component-api';\nimport type Hls from '../hls';\nimport type { FragmentTracker } from './fragment-tracker';\nimport type KeyLoader from '../loader/key-loader';\nimport type { LevelDetails } from '../loader/level-details';\nimport type { Fragment } from '../loader/fragment';\nimport type {\n  ErrorData,\n  FragLoadedData,\n  SubtitleFragProcessed,\n  SubtitleTracksUpdatedData,\n  TrackLoadedData,\n  TrackSwitchedData,\n  BufferFlushingData,\n  LevelLoadedData,\n  FragBufferedData,\n} from '../types/events';\n\nconst TICK_INTERVAL = 500; // how often to tick in ms\n\ninterface TimeRange {\n  start: number;\n  end: number;\n}\n\nexport class SubtitleStreamController\n  extends BaseStreamController\n  implements NetworkComponentAPI\n{\n  private currentTrackId: number = -1;\n  private tracksBuffered: Array<TimeRange[]> = [];\n  private mainDetails: LevelDetails | null = null;\n\n  constructor(\n    hls: Hls,\n    fragmentTracker: FragmentTracker,\n    keyLoader: KeyLoader,\n  ) {\n    super(\n      hls,\n      fragmentTracker,\n      keyLoader,\n      '[subtitle-stream-controller]',\n      PlaylistLevelType.SUBTITLE,\n    );\n    this._registerListeners();\n  }\n\n  protected onHandlerDestroying() {\n    this._unregisterListeners();\n    super.onHandlerDestroying();\n    this.mainDetails = null;\n  }\n\n  private _registerListeners() {\n    const { hls } = this;\n    hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n    hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n    hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);\n    hls.on(Events.ERROR, this.onError, this);\n    hls.on(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);\n    hls.on(Events.SUBTITLE_TRACK_SWITCH, this.onSubtitleTrackSwitch, this);\n    hls.on(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);\n    hls.on(Events.SUBTITLE_FRAG_PROCESSED, this.onSubtitleFragProcessed, this);\n    hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);\n    hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);\n  }\n\n  private _unregisterListeners() {\n    const { hls } = this;\n    hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n    hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n    hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);\n    hls.off(Events.ERROR, this.onError, this);\n    hls.off(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);\n    hls.off(Events.SUBTITLE_TRACK_SWITCH, this.onSubtitleTrackSwitch, this);\n    hls.off(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);\n    hls.off(Events.SUBTITLE_FRAG_PROCESSED, this.onSubtitleFragProcessed, this);\n    hls.off(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);\n    hls.off(Events.FRAG_BUFFERED, this.onFragBuffered, this);\n  }\n\n  startLoad(startPosition: number) {\n    this.stopLoad();\n    this.state = State.IDLE;\n\n    this.setInterval(TICK_INTERVAL);\n\n    this.nextLoadPosition =\n      this.startPosition =\n      this.lastCurrentTime =\n        startPosition;\n\n    this.tick();\n  }\n\n  onManifestLoading() {\n    this.mainDetails = null;\n    this.fragmentTracker.removeAllFragments();\n  }\n\n  onMediaDetaching(): void {\n    this.tracksBuffered = [];\n    super.onMediaDetaching();\n  }\n\n  onLevelLoaded(event: Events.LEVEL_LOADED, data: LevelLoadedData) {\n    this.mainDetails = data.details;\n  }\n\n  onSubtitleFragProcessed(\n    event: Events.SUBTITLE_FRAG_PROCESSED,\n    data: SubtitleFragProcessed,\n  ) {\n    const { frag, success } = data;\n    this.fragPrevious = frag;\n    this.state = State.IDLE;\n    if (!success) {\n      return;\n    }\n\n    const buffered = this.tracksBuffered[this.currentTrackId];\n    if (!buffered) {\n      return;\n    }\n\n    // Create/update a buffered array matching the interface used by BufferHelper.bufferedInfo\n    // so we can re-use the logic used to detect how much has been buffered\n    let timeRange: TimeRange | undefined;\n    const fragStart = frag.start;\n    for (let i = 0; i < buffered.length; i++) {\n      if (fragStart >= buffered[i].start && fragStart <= buffered[i].end) {\n        timeRange = buffered[i];\n        break;\n      }\n    }\n\n    const fragEnd = frag.start + frag.duration;\n    if (timeRange) {\n      timeRange.end = fragEnd;\n    } else {\n      timeRange = {\n        start: fragStart,\n        end: fragEnd,\n      };\n      buffered.push(timeRange);\n    }\n    this.fragmentTracker.fragBuffered(frag);\n    this.fragBufferedComplete(frag, null);\n  }\n\n  onBufferFlushing(event: Events.BUFFER_FLUSHING, data: BufferFlushingData) {\n    const { startOffset, endOffset } = data;\n    if (startOffset === 0 && endOffset !== Number.POSITIVE_INFINITY) {\n      const endOffsetSubtitles = endOffset - 1;\n      if (endOffsetSubtitles <= 0) {\n        return;\n      }\n      data.endOffsetSubtitles = Math.max(0, endOffsetSubtitles);\n      this.tracksBuffered.forEach((buffered) => {\n        for (let i = 0; i < buffered.length; ) {\n          if (buffered[i].end <= endOffsetSubtitles) {\n            buffered.shift();\n            continue;\n          } else if (buffered[i].start < endOffsetSubtitles) {\n            buffered[i].start = endOffsetSubtitles;\n          } else {\n            break;\n          }\n          i++;\n        }\n      });\n      this.fragmentTracker.removeFragmentsInRange(\n        startOffset,\n        endOffsetSubtitles,\n        PlaylistLevelType.SUBTITLE,\n      );\n    }\n  }\n\n  onFragBuffered(event: Events.FRAG_BUFFERED, data: FragBufferedData) {\n    if (!this.loadedmetadata && data.frag.type === PlaylistLevelType.MAIN) {\n      if (this.media?.buffered.length) {\n        this.loadedmetadata = true;\n      }\n    }\n  }\n\n  // If something goes wrong, proceed to next frag, if we were processing one.\n  onError(event: Events.ERROR, data: ErrorData) {\n    const frag = data.frag;\n\n    if (frag?.type === PlaylistLevelType.SUBTITLE) {\n      if (data.details === ErrorDetails.FRAG_GAP) {\n        this.fragmentTracker.fragBuffered(frag, true);\n      }\n      if (this.fragCurrent) {\n        this.fragCurrent.abortRequests();\n      }\n      if (this.state !== State.STOPPED) {\n        this.state = State.IDLE;\n      }\n    }\n  }\n\n  // Got all new subtitle levels.\n  onSubtitleTracksUpdated(\n    event: Events.SUBTITLE_TRACKS_UPDATED,\n    { subtitleTracks }: SubtitleTracksUpdatedData,\n  ) {\n    if (this.levels && subtitleOptionsIdentical(this.levels, subtitleTracks)) {\n      this.levels = subtitleTracks.map(\n        (mediaPlaylist) => new Level(mediaPlaylist),\n      );\n      return;\n    }\n    this.tracksBuffered = [];\n    this.levels = subtitleTracks.map((mediaPlaylist) => {\n      const level = new Level(mediaPlaylist);\n      this.tracksBuffered[level.id] = [];\n      return level;\n    });\n    this.fragmentTracker.removeFragmentsInRange(\n      0,\n      Number.POSITIVE_INFINITY,\n      PlaylistLevelType.SUBTITLE,\n    );\n    this.fragPrevious = null;\n    this.mediaBuffer = null;\n  }\n\n  onSubtitleTrackSwitch(\n    event: Events.SUBTITLE_TRACK_SWITCH,\n    data: TrackSwitchedData,\n  ) {\n    this.currentTrackId = data.id;\n\n    if (!this.levels?.length || this.currentTrackId === -1) {\n      this.clearInterval();\n      return;\n    }\n\n    // Check if track has the necessary details to load fragments\n    const currentTrack = this.levels[this.currentTrackId];\n    if (currentTrack?.details) {\n      this.mediaBuffer = this.mediaBufferTimeRanges;\n    } else {\n      this.mediaBuffer = null;\n    }\n    if (currentTrack) {\n      this.setInterval(TICK_INTERVAL);\n    }\n  }\n\n  // Got a new set of subtitle fragments.\n  onSubtitleTrackLoaded(\n    event: Events.SUBTITLE_TRACK_LOADED,\n    data: TrackLoadedData,\n  ) {\n    const { currentTrackId, levels } = this;\n    const { details: newDetails, id: trackId } = data;\n    if (!levels) {\n      this.warn(`Subtitle tracks were reset while loading level ${trackId}`);\n      return;\n    }\n    const track: Level = levels[trackId];\n    if (trackId >= levels.length || !track) {\n      return;\n    }\n    this.log(\n      `Subtitle track ${trackId} loaded [${newDetails.startSN},${\n        newDetails.endSN\n      }]${\n        newDetails.lastPartSn\n          ? `[part-${newDetails.lastPartSn}-${newDetails.lastPartIndex}]`\n          : ''\n      },duration:${newDetails.totalduration}`,\n    );\n    this.mediaBuffer = this.mediaBufferTimeRanges;\n    let sliding = 0;\n    if (newDetails.live || track.details?.live) {\n      const mainDetails = this.mainDetails;\n      if (newDetails.deltaUpdateFailed || !mainDetails) {\n        return;\n      }\n      const mainSlidingStartFragment = mainDetails.fragments[0];\n      if (!track.details) {\n        if (newDetails.hasProgramDateTime && mainDetails.hasProgramDateTime) {\n          alignMediaPlaylistByPDT(newDetails, mainDetails);\n          sliding = newDetails.fragments[0].start;\n        } else if (mainSlidingStartFragment) {\n          // line up live playlist with main so that fragments in range are loaded\n          sliding = mainSlidingStartFragment.start;\n          addSliding(newDetails, sliding);\n        }\n      } else {\n        sliding = this.alignPlaylists(\n          newDetails,\n          track.details,\n          this.levelLastLoaded?.details,\n        );\n        if (sliding === 0 && mainSlidingStartFragment) {\n          // realign with main when there is no overlap with last refresh\n          sliding = mainSlidingStartFragment.start;\n          addSliding(newDetails, sliding);\n        }\n      }\n    }\n    track.details = newDetails;\n    this.levelLastLoaded = track;\n\n    if (trackId !== currentTrackId) {\n      return;\n    }\n\n    if (!this.startFragRequested && (this.mainDetails || !newDetails.live)) {\n      this.setStartPosition(this.mainDetails || newDetails, sliding);\n    }\n\n    // trigger handler right now\n    this.tick();\n\n    // If playlist is misaligned because of bad PDT or drift, delete details to resync with main on reload\n    if (\n      newDetails.live &&\n      !this.fragCurrent &&\n      this.media &&\n      this.state === State.IDLE\n    ) {\n      const foundFrag = findFragmentByPTS(\n        null,\n        newDetails.fragments,\n        this.media.currentTime,\n        0,\n      );\n      if (!foundFrag) {\n        this.warn('Subtitle playlist not aligned with playback');\n        track.details = undefined;\n      }\n    }\n  }\n\n  _handleFragmentLoadComplete(fragLoadedData: FragLoadedData) {\n    const { frag, payload } = fragLoadedData;\n    const decryptData = frag.decryptdata;\n    const hls = this.hls;\n\n    if (this.fragContextChanged(frag)) {\n      return;\n    }\n    // check to see if the payload needs to be decrypted\n    if (\n      payload &&\n      payload.byteLength > 0 &&\n      decryptData?.key &&\n      decryptData.iv &&\n      decryptData.method === 'AES-128'\n    ) {\n      const startTime = performance.now();\n      // decrypt the subtitles\n      this.decrypter\n        .decrypt(\n          new Uint8Array(payload),\n          decryptData.key.buffer,\n          decryptData.iv.buffer,\n        )\n        .catch((err) => {\n          hls.trigger(Events.ERROR, {\n            type: ErrorTypes.MEDIA_ERROR,\n            details: ErrorDetails.FRAG_DECRYPT_ERROR,\n            fatal: false,\n            error: err,\n            reason: err.message,\n            frag,\n          });\n          throw err;\n        })\n        .then((decryptedData) => {\n          const endTime = performance.now();\n          hls.trigger(Events.FRAG_DECRYPTED, {\n            frag,\n            payload: decryptedData,\n            stats: {\n              tstart: startTime,\n              tdecrypt: endTime,\n            },\n          });\n        })\n        .catch((err) => {\n          this.warn(`${err.name}: ${err.message}`);\n          this.state = State.IDLE;\n        });\n    }\n  }\n\n  doTick() {\n    if (!this.media) {\n      this.state = State.IDLE;\n      return;\n    }\n\n    if (this.state === State.IDLE) {\n      const { currentTrackId, levels } = this;\n      const track = levels?.[currentTrackId];\n      if (!track || !levels.length || !track.details) {\n        return;\n      }\n      const { config } = this;\n      const currentTime = this.getLoadPosition();\n      const bufferedInfo = BufferHelper.bufferedInfo(\n        this.tracksBuffered[this.currentTrackId] || [],\n        currentTime,\n        config.maxBufferHole,\n      );\n      const { end: targetBufferTime, len: bufferLen } = bufferedInfo;\n\n      const mainBufferInfo = this.getFwdBufferInfo(\n        this.media,\n        PlaylistLevelType.MAIN,\n      );\n      const trackDetails = track.details as LevelDetails;\n      const maxBufLen =\n        this.getMaxBufferLength(mainBufferInfo?.len) +\n        trackDetails.levelTargetDuration;\n\n      if (bufferLen > maxBufLen) {\n        return;\n      }\n      const fragments = trackDetails.fragments;\n      const fragLen = fragments.length;\n      const end = trackDetails.edge;\n\n      let foundFrag: Fragment | null = null;\n      const fragPrevious = this.fragPrevious;\n      if (targetBufferTime < end) {\n        const tolerance = config.maxFragLookUpTolerance;\n        const lookupTolerance =\n          targetBufferTime > end - tolerance ? 0 : tolerance;\n        foundFrag = findFragmentByPTS(\n          fragPrevious,\n          fragments,\n          Math.max(fragments[0].start, targetBufferTime),\n          lookupTolerance,\n        );\n        if (\n          !foundFrag &&\n          fragPrevious &&\n          fragPrevious.start < fragments[0].start\n        ) {\n          foundFrag = fragments[0];\n        }\n      } else {\n        foundFrag = fragments[fragLen - 1];\n      }\n      if (!foundFrag) {\n        return;\n      }\n      foundFrag = this.mapToInitFragWhenRequired(foundFrag) as Fragment;\n      if (foundFrag.sn !== 'initSegment') {\n        // Load earlier fragment in same discontinuity to make up for misaligned playlists and cues that extend beyond end of segment\n        const curSNIdx = foundFrag.sn - trackDetails.startSN;\n        const prevFrag = fragments[curSNIdx - 1];\n        if (\n          prevFrag &&\n          prevFrag.cc === foundFrag.cc &&\n          this.fragmentTracker.getState(prevFrag) === FragmentState.NOT_LOADED\n        ) {\n          foundFrag = prevFrag;\n        }\n      }\n      if (\n        this.fragmentTracker.getState(foundFrag) === FragmentState.NOT_LOADED\n      ) {\n        // only load if fragment is not loaded\n        this.loadFragment(foundFrag, track, targetBufferTime);\n      }\n    }\n  }\n\n  protected getMaxBufferLength(mainBufferLength?: number): number {\n    const maxConfigBuffer = super.getMaxBufferLength();\n    if (!mainBufferLength) {\n      return maxConfigBuffer;\n    }\n    return Math.max(maxConfigBuffer, mainBufferLength);\n  }\n\n  protected loadFragment(\n    frag: Fragment,\n    level: Level,\n    targetBufferTime: number,\n  ) {\n    this.fragCurrent = frag;\n    if (frag.sn === 'initSegment') {\n      this._loadInitSegment(frag, level);\n    } else {\n      this.startFragRequested = true;\n      super.loadFragment(frag, level, targetBufferTime);\n    }\n  }\n\n  get mediaBufferTimeRanges(): Bufferable {\n    return new BufferableInstance(\n      this.tracksBuffered[this.currentTrackId] || [],\n    );\n  }\n}\n\nclass BufferableInstance implements Bufferable {\n  public readonly buffered: TimeRanges;\n\n  constructor(timeranges: TimeRange[]) {\n    const getRange = (\n      name: 'start' | 'end',\n      index: number,\n      length: number,\n    ): number => {\n      index = index >>> 0;\n      if (index > length - 1) {\n        throw new DOMException(\n          `Failed to execute '${name}' on 'TimeRanges': The index provided (${index}) is greater than the maximum bound (${length})`,\n        );\n      }\n      return timeranges[index][name];\n    };\n    this.buffered = {\n      get length() {\n        return timeranges.length;\n      },\n      end(index: number): number {\n        return getRange('end', index, timeranges.length);\n      },\n      start(index: number): number {\n        return getRange('start', index, timeranges.length);\n      },\n    };\n  }\n}\n", "import BasePlaylistController from './base-playlist-controller';\nimport { Events } from '../events';\nimport {\n  clearCurrentCues,\n  filterSubtitleTracks,\n} from '../utils/texttrack-utils';\nimport { PlaylistContextType } from '../types/loader';\nimport {\n  mediaAttributesIdentical,\n  subtitleTrackMatchesTextTrack,\n} from '../utils/media-option-attributes';\nimport { findMatchingOption, matchesOption } from '../utils/rendition-helper';\nimport type Hls from '../hls';\nimport type {\n  MediaPlaylist,\n  SubtitleSelectionOption,\n} from '../types/media-playlist';\nimport type { HlsUrlParameters } from '../types/level';\nimport type {\n  ErrorData,\n  LevelLoadingData,\n  MediaAttachedData,\n  SubtitleTracksUpdatedData,\n  ManifestParsedData,\n  TrackLoadedData,\n  LevelSwitchingData,\n} from '../types/events';\n\nclass SubtitleTrackController extends BasePlaylistController {\n  private media: HTMLMediaElement | null = null;\n  private tracks: MediaPlaylist[] = [];\n  private groupIds: (string | undefined)[] | null = null;\n  private tracksInGroup: MediaPlaylist[] = [];\n  private trackId: number = -1;\n  private currentTrack: MediaPlaylist | null = null;\n  private selectDefaultTrack: boolean = true;\n  private queuedDefaultTrack: number = -1;\n  private asyncPollTrackChange: () => void = () => this.pollTrackChange(0);\n  private useTextTrackPolling: boolean = false;\n  private subtitlePollingInterval: number = -1;\n  private _subtitleDisplay: boolean = true;\n\n  constructor(hls: Hls) {\n    super(hls, '[subtitle-track-controller]');\n    this.registerListeners();\n  }\n\n  public destroy() {\n    this.unregisterListeners();\n    this.tracks.length = 0;\n    this.tracksInGroup.length = 0;\n    this.currentTrack = null;\n    this.onTextTracksChanged = this.asyncPollTrackChange = null as any;\n    super.destroy();\n  }\n\n  public get subtitleDisplay(): boolean {\n    return this._subtitleDisplay;\n  }\n\n  public set subtitleDisplay(value: boolean) {\n    this._subtitleDisplay = value;\n    if (this.trackId > -1) {\n      this.toggleTrackModes();\n    }\n  }\n\n  private registerListeners() {\n    const { hls } = this;\n    hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n    hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n    hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    hls.on(Events.MANIFEST_PARSED, this.onManifestParsed, this);\n    hls.on(Events.LEVEL_LOADING, this.onLevelLoading, this);\n    hls.on(Events.LEVEL_SWITCHING, this.onLevelSwitching, this);\n    hls.on(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);\n    hls.on(Events.ERROR, this.onError, this);\n  }\n\n  private unregisterListeners() {\n    const { hls } = this;\n    hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n    hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n    hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    hls.off(Events.MANIFEST_PARSED, this.onManifestParsed, this);\n    hls.off(Events.LEVEL_LOADING, this.onLevelLoading, this);\n    hls.off(Events.LEVEL_SWITCHING, this.onLevelSwitching, this);\n    hls.off(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);\n    hls.off(Events.ERROR, this.onError, this);\n  }\n\n  // Listen for subtitle track change, then extract the current track ID.\n  protected onMediaAttached(\n    event: Events.MEDIA_ATTACHED,\n    data: MediaAttachedData,\n  ): void {\n    this.media = data.media;\n    if (!this.media) {\n      return;\n    }\n\n    if (this.queuedDefaultTrack > -1) {\n      this.subtitleTrack = this.queuedDefaultTrack;\n      this.queuedDefaultTrack = -1;\n    }\n\n    this.useTextTrackPolling = !(\n      this.media.textTracks && 'onchange' in this.media.textTracks\n    );\n    if (this.useTextTrackPolling) {\n      this.pollTrackChange(500);\n    } else {\n      this.media.textTracks.addEventListener(\n        'change',\n        this.asyncPollTrackChange,\n      );\n    }\n  }\n\n  private pollTrackChange(timeout: number) {\n    self.clearInterval(this.subtitlePollingInterval);\n    this.subtitlePollingInterval = self.setInterval(\n      this.onTextTracksChanged,\n      timeout,\n    );\n  }\n\n  protected onMediaDetaching(): void {\n    if (!this.media) {\n      return;\n    }\n\n    self.clearInterval(this.subtitlePollingInterval);\n    if (!this.useTextTrackPolling) {\n      this.media.textTracks.removeEventListener(\n        'change',\n        this.asyncPollTrackChange,\n      );\n    }\n\n    if (this.trackId > -1) {\n      this.queuedDefaultTrack = this.trackId;\n    }\n\n    const textTracks = filterSubtitleTracks(this.media.textTracks);\n    // Clear loaded cues on media detachment from tracks\n    textTracks.forEach((track) => {\n      clearCurrentCues(track);\n    });\n    // Disable all subtitle tracks before detachment so when reattached only tracks in that content are enabled.\n    this.subtitleTrack = -1;\n    this.media = null;\n  }\n\n  protected onManifestLoading(): void {\n    this.tracks = [];\n    this.groupIds = null;\n    this.tracksInGroup = [];\n    this.trackId = -1;\n    this.currentTrack = null;\n    this.selectDefaultTrack = true;\n  }\n\n  // Fired whenever a new manifest is loaded.\n  protected onManifestParsed(\n    event: Events.MANIFEST_PARSED,\n    data: ManifestParsedData,\n  ): void {\n    this.tracks = data.subtitleTracks;\n  }\n\n  protected onSubtitleTrackLoaded(\n    event: Events.SUBTITLE_TRACK_LOADED,\n    data: TrackLoadedData,\n  ): void {\n    const { id, groupId, details } = data;\n    const trackInActiveGroup = this.tracksInGroup[id];\n\n    if (!trackInActiveGroup || trackInActiveGroup.groupId !== groupId) {\n      this.warn(\n        `Subtitle track with id:${id} and group:${groupId} not found in active group ${trackInActiveGroup?.groupId}`,\n      );\n      return;\n    }\n\n    const curDetails = trackInActiveGroup.details;\n    trackInActiveGroup.details = data.details;\n    this.log(\n      `Subtitle track ${id} \"${trackInActiveGroup.name}\" lang:${trackInActiveGroup.lang} group:${groupId} loaded [${details.startSN}-${details.endSN}]`,\n    );\n\n    if (id === this.trackId) {\n      this.playlistLoaded(id, data, curDetails);\n    }\n  }\n\n  protected onLevelLoading(\n    event: Events.LEVEL_LOADING,\n    data: LevelLoadingData,\n  ): void {\n    this.switchLevel(data.level);\n  }\n\n  protected onLevelSwitching(\n    event: Events.LEVEL_SWITCHING,\n    data: LevelSwitchingData,\n  ): void {\n    this.switchLevel(data.level);\n  }\n\n  private switchLevel(levelIndex: number) {\n    const levelInfo = this.hls.levels[levelIndex];\n    if (!levelInfo) {\n      return;\n    }\n    const subtitleGroups = levelInfo.subtitleGroups || null;\n    const currentGroups = this.groupIds;\n    let currentTrack = this.currentTrack;\n    if (\n      !subtitleGroups ||\n      currentGroups?.length !== subtitleGroups?.length ||\n      subtitleGroups?.some((groupId) => currentGroups?.indexOf(groupId) === -1)\n    ) {\n      this.groupIds = subtitleGroups;\n      this.trackId = -1;\n      this.currentTrack = null;\n\n      const subtitleTracks = this.tracks.filter(\n        (track): boolean =>\n          !subtitleGroups || subtitleGroups.indexOf(track.groupId) !== -1,\n      );\n      if (subtitleTracks.length) {\n        // Disable selectDefaultTrack if there are no default tracks\n        if (\n          this.selectDefaultTrack &&\n          !subtitleTracks.some((track) => track.default)\n        ) {\n          this.selectDefaultTrack = false;\n        }\n        // track.id should match hls.audioTracks index\n        subtitleTracks.forEach((track, i) => {\n          track.id = i;\n        });\n      } else if (!currentTrack && !this.tracksInGroup.length) {\n        // Do not dispatch SUBTITLE_TRACKS_UPDATED when there were and are no tracks\n        return;\n      }\n      this.tracksInGroup = subtitleTracks;\n\n      // Find preferred track\n      const subtitlePreference = this.hls.config.subtitlePreference;\n      if (!currentTrack && subtitlePreference) {\n        this.selectDefaultTrack = false;\n        const groupIndex = findMatchingOption(\n          subtitlePreference,\n          subtitleTracks,\n        );\n        if (groupIndex > -1) {\n          currentTrack = subtitleTracks[groupIndex];\n        } else {\n          const allIndex = findMatchingOption(subtitlePreference, this.tracks);\n          currentTrack = this.tracks[allIndex];\n        }\n      }\n\n      // Select initial track\n      let trackId = this.findTrackId(currentTrack);\n      if (trackId === -1 && currentTrack) {\n        trackId = this.findTrackId(null);\n      }\n\n      // Dispatch events and load track if needed\n      const subtitleTracksUpdated: SubtitleTracksUpdatedData = {\n        subtitleTracks,\n      };\n      this.log(\n        `Updating subtitle tracks, ${\n          subtitleTracks.length\n        } track(s) found in \"${subtitleGroups?.join(',')}\" group-id`,\n      );\n      this.hls.trigger(Events.SUBTITLE_TRACKS_UPDATED, subtitleTracksUpdated);\n\n      if (trackId !== -1 && this.trackId === -1) {\n        this.setSubtitleTrack(trackId);\n      }\n    } else if (this.shouldReloadPlaylist(currentTrack)) {\n      // Retry playlist loading if no playlist is or has been loaded yet\n      this.setSubtitleTrack(this.trackId);\n    }\n  }\n\n  private findTrackId(currentTrack: MediaPlaylist | null): number {\n    const tracks = this.tracksInGroup;\n    const selectDefault = this.selectDefaultTrack;\n    for (let i = 0; i < tracks.length; i++) {\n      const track = tracks[i];\n      if (\n        (selectDefault && !track.default) ||\n        (!selectDefault && !currentTrack)\n      ) {\n        continue;\n      }\n      if (!currentTrack || matchesOption(track, currentTrack)) {\n        return i;\n      }\n    }\n    if (currentTrack) {\n      for (let i = 0; i < tracks.length; i++) {\n        const track = tracks[i];\n        if (\n          mediaAttributesIdentical(currentTrack.attrs, track.attrs, [\n            'LANGUAGE',\n            'ASSOC-LANGUAGE',\n            'CHARACTERISTICS',\n          ])\n        ) {\n          return i;\n        }\n      }\n      for (let i = 0; i < tracks.length; i++) {\n        const track = tracks[i];\n        if (\n          mediaAttributesIdentical(currentTrack.attrs, track.attrs, [\n            'LANGUAGE',\n          ])\n        ) {\n          return i;\n        }\n      }\n    }\n    return -1;\n  }\n\n  private findTrackForTextTrack(textTrack: TextTrack | null): number {\n    if (textTrack) {\n      const tracks = this.tracksInGroup;\n      for (let i = 0; i < tracks.length; i++) {\n        const track = tracks[i];\n        if (subtitleTrackMatchesTextTrack(track, textTrack)) {\n          return i;\n        }\n      }\n    }\n    return -1;\n  }\n\n  protected onError(event: Events.ERROR, data: ErrorData): void {\n    if (data.fatal || !data.context) {\n      return;\n    }\n\n    if (\n      data.context.type === PlaylistContextType.SUBTITLE_TRACK &&\n      data.context.id === this.trackId &&\n      (!this.groupIds || this.groupIds.indexOf(data.context.groupId) !== -1)\n    ) {\n      this.checkRetry(data);\n    }\n  }\n\n  get allSubtitleTracks(): MediaPlaylist[] {\n    return this.tracks;\n  }\n\n  /** get alternate subtitle tracks list from playlist **/\n  get subtitleTracks(): MediaPlaylist[] {\n    return this.tracksInGroup;\n  }\n\n  /** get/set index of the selected subtitle track (based on index in subtitle track lists) **/\n  get subtitleTrack(): number {\n    return this.trackId;\n  }\n\n  set subtitleTrack(newId: number) {\n    this.selectDefaultTrack = false;\n    this.setSubtitleTrack(newId);\n  }\n\n  public setSubtitleOption(\n    subtitleOption: MediaPlaylist | SubtitleSelectionOption | undefined,\n  ): MediaPlaylist | null {\n    this.hls.config.subtitlePreference = subtitleOption;\n    if (subtitleOption) {\n      const allSubtitleTracks = this.allSubtitleTracks;\n      this.selectDefaultTrack = false;\n      if (allSubtitleTracks.length) {\n        // First see if current option matches (no switch op)\n        const currentTrack = this.currentTrack;\n        if (currentTrack && matchesOption(subtitleOption, currentTrack)) {\n          return currentTrack;\n        }\n        // Find option in current group\n        const groupIndex = findMatchingOption(\n          subtitleOption,\n          this.tracksInGroup,\n        );\n        if (groupIndex > -1) {\n          const track = this.tracksInGroup[groupIndex];\n          this.setSubtitleTrack(groupIndex);\n          return track;\n        } else if (currentTrack) {\n          // If this is not the initial selection return null\n          // option should have matched one in active group\n          return null;\n        } else {\n          // Find the option in all tracks for initial selection\n          const allIndex = findMatchingOption(\n            subtitleOption,\n            allSubtitleTracks,\n          );\n          if (allIndex > -1) {\n            return allSubtitleTracks[allIndex];\n          }\n        }\n      }\n    }\n    return null;\n  }\n\n  protected loadPlaylist(hlsUrlParameters?: HlsUrlParameters): void {\n    super.loadPlaylist();\n    const currentTrack = this.currentTrack;\n    if (this.shouldLoadPlaylist(currentTrack) && currentTrack) {\n      const id = currentTrack.id;\n      const groupId = currentTrack.groupId as string;\n      let url = currentTrack.url;\n      if (hlsUrlParameters) {\n        try {\n          url = hlsUrlParameters.addDirectives(url);\n        } catch (error) {\n          this.warn(\n            `Could not construct new URL with HLS Delivery Directives: ${error}`,\n          );\n        }\n      }\n      this.log(`Loading subtitle playlist for id ${id}`);\n      this.hls.trigger(Events.SUBTITLE_TRACK_LOADING, {\n        url,\n        id,\n        groupId,\n        deliveryDirectives: hlsUrlParameters || null,\n      });\n    }\n  }\n\n  /**\n   * Disables the old subtitleTrack and sets current mode on the next subtitleTrack.\n   * This operates on the DOM textTracks.\n   * A value of -1 will disable all subtitle tracks.\n   */\n  private toggleTrackModes(): void {\n    const { media } = this;\n    if (!media) {\n      return;\n    }\n\n    const textTracks = filterSubtitleTracks(media.textTracks);\n    const currentTrack = this.currentTrack;\n    let nextTrack;\n    if (currentTrack) {\n      nextTrack = textTracks.filter((textTrack) =>\n        subtitleTrackMatchesTextTrack(currentTrack, textTrack),\n      )[0];\n      if (!nextTrack) {\n        this.warn(\n          `Unable to find subtitle TextTrack with name \"${currentTrack.name}\" and language \"${currentTrack.lang}\"`,\n        );\n      }\n    }\n    [].slice.call(textTracks).forEach((track) => {\n      if (track.mode !== 'disabled' && track !== nextTrack) {\n        track.mode = 'disabled';\n      }\n    });\n    if (nextTrack) {\n      const mode = this.subtitleDisplay ? 'showing' : 'hidden';\n      if (nextTrack.mode !== mode) {\n        nextTrack.mode = mode;\n      }\n    }\n  }\n\n  /**\n   * This method is responsible for validating the subtitle index and periodically reloading if live.\n   * Dispatches the SUBTITLE_TRACK_SWITCH event, which instructs the subtitle-stream-controller to load the selected track.\n   */\n  private setSubtitleTrack(newId: number): void {\n    const tracks = this.tracksInGroup;\n\n    // setting this.subtitleTrack will trigger internal logic\n    // if media has not been attached yet, it will fail\n    // we keep a reference to the default track id\n    // and we'll set subtitleTrack when onMediaAttached is triggered\n    if (!this.media) {\n      this.queuedDefaultTrack = newId;\n      return;\n    }\n\n    // exit if track id as already set or invalid\n    if (newId < -1 || newId >= tracks.length || !Number.isFinite(newId)) {\n      this.warn(`Invalid subtitle track id: ${newId}`);\n      return;\n    }\n\n    // stopping live reloading timer if any\n    this.clearTimer();\n\n    this.selectDefaultTrack = false;\n    const lastTrack = this.currentTrack;\n    const track: MediaPlaylist | null = tracks[newId] || null;\n    this.trackId = newId;\n    this.currentTrack = track;\n    this.toggleTrackModes();\n    if (!track) {\n      // switch to -1\n      this.hls.trigger(Events.SUBTITLE_TRACK_SWITCH, { id: newId });\n      return;\n    }\n    const trackLoaded = !!track.details && !track.details.live;\n    if (newId === this.trackId && track === lastTrack && trackLoaded) {\n      return;\n    }\n    this.log(\n      `Switching to subtitle-track ${newId}` +\n        (track\n          ? ` \"${track.name}\" lang:${track.lang} group:${track.groupId}`\n          : ''),\n    );\n    const { id, groupId = '', name, type, url } = track;\n    this.hls.trigger(Events.SUBTITLE_TRACK_SWITCH, {\n      id,\n      groupId,\n      name,\n      type,\n      url,\n    });\n    const hlsUrlParameters = this.switchParams(\n      track.url,\n      lastTrack?.details,\n      track.details,\n    );\n    this.loadPlaylist(hlsUrlParameters);\n  }\n\n  private onTextTracksChanged = () => {\n    if (!this.useTextTrackPolling) {\n      self.clearInterval(this.subtitlePollingInterval);\n    }\n    // Media is undefined when switching streams via loadSource()\n    if (!this.media || !this.hls.config.renderTextTracksNatively) {\n      return;\n    }\n\n    let textTrack: TextTrack | null = null;\n    const tracks = filterSubtitleTracks(this.media.textTracks);\n    for (let i = 0; i < tracks.length; i++) {\n      if (tracks[i].mode === 'hidden') {\n        // Do not break in case there is a following track with showing.\n        textTrack = tracks[i];\n      } else if (tracks[i].mode === 'showing') {\n        textTrack = tracks[i];\n        break;\n      }\n    }\n\n    // Find internal track index for TextTrack\n    const trackId = this.findTrackForTextTrack(textTrack);\n    if (this.subtitleTrack !== trackId) {\n      this.setSubtitleTrack(trackId);\n    }\n  };\n}\n\nexport default SubtitleTrackController;\n", "import { logger } from '../utils/logger';\nimport type {\n  BufferOperation,\n  BufferOperationQueues,\n  SourceBuffers,\n  SourceBufferName,\n} from '../types/buffer';\n\nexport default class BufferOperationQueue {\n  private buffers: SourceBuffers;\n  private queues: BufferOperationQueues = {\n    video: [],\n    audio: [],\n    audiovideo: [],\n  };\n\n  constructor(sourceBufferReference: SourceBuffers) {\n    this.buffers = sourceBufferReference;\n  }\n\n  public append(\n    operation: BufferOperation,\n    type: SourceBufferName,\n    pending?: boolean,\n  ) {\n    const queue = this.queues[type];\n    queue.push(operation);\n    if (queue.length === 1 && !pending) {\n      this.executeNext(type);\n    }\n  }\n\n  public insertAbort(operation: BufferOperation, type: SourceBufferName) {\n    const queue = this.queues[type];\n    queue.unshift(operation);\n    this.executeNext(type);\n  }\n\n  public appendBlocker(type: SourceBufferName): Promise<{}> {\n    let execute;\n    const promise: Promise<{}> = new Promise((resolve) => {\n      execute = resolve;\n    });\n    const operation: BufferOperation = {\n      execute,\n      onStart: () => {},\n      onComplete: () => {},\n      onError: () => {},\n    };\n\n    this.append(operation, type);\n    return promise;\n  }\n\n  public executeNext(type: SourceBufferName) {\n    const queue = this.queues[type];\n    if (queue.length) {\n      const operation: BufferOperation = queue[0];\n      try {\n        // Operations are expected to result in an 'updateend' event being fired. If not, the queue will lock. Operations\n        // which do not end with this event must call _onSBUpdateEnd manually\n        operation.execute();\n      } catch (error) {\n        logger.warn(\n          `[buffer-operation-queue]: Exception executing \"${type}\" SourceBuffer operation: ${error}`,\n        );\n        operation.onError(error);\n\n        // Only shift the current operation off, otherwise the updateend handler will do this for us\n        const sb = this.buffers[type];\n        if (!sb?.updating) {\n          this.shiftAndExecuteNext(type);\n        }\n      }\n    }\n  }\n\n  public shiftAndExecuteNext(type: SourceBufferName) {\n    this.queues[type].shift();\n    this.executeNext(type);\n  }\n\n  public current(type: SourceBufferName) {\n    return this.queues[type][0];\n  }\n}\n", "import { Events } from '../events';\nimport { logger } from '../utils/logger';\nimport { ErrorDetails, ErrorTypes } from '../errors';\nimport { BufferHelper } from '../utils/buffer-helper';\nimport {\n  getCodecCompatibleName,\n  pickMostCompleteCodecName,\n} from '../utils/codecs';\nimport {\n  getMediaSource,\n  isManagedMediaSource,\n} from '../utils/mediasource-helper';\nimport { ElementaryStreamTypes } from '../loader/fragment';\nimport type { TrackSet } from '../types/track';\nimport BufferOperationQueue from './buffer-operation-queue';\nimport {\n  BufferOperation,\n  SourceBuffers,\n  SourceBufferName,\n  SourceBufferListeners,\n} from '../types/buffer';\nimport type {\n  LevelUpdatedData,\n  BufferAppendingData,\n  MediaAttachingData,\n  ManifestParsedData,\n  BufferCodecsData,\n  BufferEOSData,\n  BufferFlushingData,\n  FragParsedData,\n  FragChangedData,\n  ErrorData,\n} from '../types/events';\nimport type { ComponentAPI } from '../types/component-api';\nimport type { ChunkMetadata } from '../types/transmuxer';\nimport type Hls from '../hls';\nimport type { LevelDetails } from '../loader/level-details';\nimport type { HlsConfig } from '../config';\n\nconst VIDEO_CODEC_PROFILE_REPLACE =\n  /(avc[1234]|hvc1|hev1|dvh[1e]|vp09|av01)(?:\\.[^.,]+)+/;\n\ninterface BufferedChangeEvent extends Event {\n  readonly addedRanges?: TimeRanges;\n  readonly removedRanges?: TimeRanges;\n}\n\nexport default class BufferController implements ComponentAPI {\n  // The level details used to determine duration, target-duration and live\n  private details: LevelDetails | null = null;\n  // cache the self generated object url to detect hijack of video tag\n  private _objectUrl: string | null = null;\n  // A queue of buffer operations which require the SourceBuffer to not be updating upon execution\n  private operationQueue!: BufferOperationQueue;\n  // References to event listeners for each SourceBuffer, so that they can be referenced for event removal\n  private listeners!: SourceBufferListeners;\n\n  private hls: Hls;\n\n  // The number of BUFFER_CODEC events received before any sourceBuffers are created\n  public bufferCodecEventsExpected: number = 0;\n\n  // The total number of BUFFER_CODEC events received\n  private _bufferCodecEventsTotal: number = 0;\n\n  // A reference to the attached media element\n  public media: HTMLMediaElement | null = null;\n\n  // A reference to the active media source\n  public mediaSource: MediaSource | null = null;\n\n  // Last MP3 audio chunk appended\n  private lastMpegAudioChunk: ChunkMetadata | null = null;\n\n  private appendSource: boolean;\n\n  // counters\n  public appendErrors = {\n    audio: 0,\n    video: 0,\n    audiovideo: 0,\n  };\n\n  public tracks: TrackSet = {};\n  public pendingTracks: TrackSet = {};\n  public sourceBuffer!: SourceBuffers;\n\n  protected log: (msg: any) => void;\n  protected warn: (msg: any, obj?: any) => void;\n  protected error: (msg: any, obj?: any) => void;\n\n  constructor(hls: Hls) {\n    this.hls = hls;\n    const logPrefix = '[buffer-controller]';\n    this.appendSource = isManagedMediaSource(\n      getMediaSource(hls.config.preferManagedMediaSource),\n    );\n    this.log = logger.log.bind(logger, logPrefix);\n    this.warn = logger.warn.bind(logger, logPrefix);\n    this.error = logger.error.bind(logger, logPrefix);\n    this._initSourceBuffer();\n    this.registerListeners();\n  }\n\n  public hasSourceTypes(): boolean {\n    return (\n      this.getSourceBufferTypes().length > 0 ||\n      Object.keys(this.pendingTracks).length > 0\n    );\n  }\n\n  public destroy() {\n    this.unregisterListeners();\n    this.details = null;\n    this.lastMpegAudioChunk = null;\n    // @ts-ignore\n    this.hls = null;\n  }\n\n  protected registerListeners() {\n    const { hls } = this;\n    hls.on(Events.MEDIA_ATTACHING, this.onMediaAttaching, this);\n    hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n    hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    hls.on(Events.MANIFEST_PARSED, this.onManifestParsed, this);\n    hls.on(Events.BUFFER_RESET, this.onBufferReset, this);\n    hls.on(Events.BUFFER_APPENDING, this.onBufferAppending, this);\n    hls.on(Events.BUFFER_CODECS, this.onBufferCodecs, this);\n    hls.on(Events.BUFFER_EOS, this.onBufferEos, this);\n    hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);\n    hls.on(Events.LEVEL_UPDATED, this.onLevelUpdated, this);\n    hls.on(Events.FRAG_PARSED, this.onFragParsed, this);\n    hls.on(Events.FRAG_CHANGED, this.onFragChanged, this);\n  }\n\n  protected unregisterListeners() {\n    const { hls } = this;\n    hls.off(Events.MEDIA_ATTACHING, this.onMediaAttaching, this);\n    hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n    hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    hls.off(Events.MANIFEST_PARSED, this.onManifestParsed, this);\n    hls.off(Events.BUFFER_RESET, this.onBufferReset, this);\n    hls.off(Events.BUFFER_APPENDING, this.onBufferAppending, this);\n    hls.off(Events.BUFFER_CODECS, this.onBufferCodecs, this);\n    hls.off(Events.BUFFER_EOS, this.onBufferEos, this);\n    hls.off(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);\n    hls.off(Events.LEVEL_UPDATED, this.onLevelUpdated, this);\n    hls.off(Events.FRAG_PARSED, this.onFragParsed, this);\n    hls.off(Events.FRAG_CHANGED, this.onFragChanged, this);\n  }\n\n  private _initSourceBuffer() {\n    this.sourceBuffer = {};\n    this.operationQueue = new BufferOperationQueue(this.sourceBuffer);\n    this.listeners = {\n      audio: [],\n      video: [],\n      audiovideo: [],\n    };\n    this.appendErrors = {\n      audio: 0,\n      video: 0,\n      audiovideo: 0,\n    };\n    this.lastMpegAudioChunk = null;\n  }\n\n  private onManifestLoading() {\n    this.bufferCodecEventsExpected = this._bufferCodecEventsTotal = 0;\n    this.details = null;\n  }\n\n  protected onManifestParsed(\n    event: Events.MANIFEST_PARSED,\n    data: ManifestParsedData,\n  ) {\n    // in case of alt audio 2 BUFFER_CODECS events will be triggered, one per stream controller\n    // sourcebuffers will be created all at once when the expected nb of tracks will be reached\n    // in case alt audio is not used, only one BUFFER_CODEC event will be fired from main stream controller\n    // it will contain the expected nb of source buffers, no need to compute it\n    let codecEvents: number = 2;\n    if ((data.audio && !data.video) || !data.altAudio || !__USE_ALT_AUDIO__) {\n      codecEvents = 1;\n    }\n    this.bufferCodecEventsExpected = this._bufferCodecEventsTotal = codecEvents;\n    this.log(`${this.bufferCodecEventsExpected} bufferCodec event(s) expected`);\n  }\n\n  protected onMediaAttaching(\n    event: Events.MEDIA_ATTACHING,\n    data: MediaAttachingData,\n  ) {\n    const media = (this.media = data.media);\n    const MediaSource = getMediaSource(this.appendSource);\n\n    if (media && MediaSource) {\n      const ms = (this.mediaSource = new MediaSource());\n      this.log(`created media source: ${ms.constructor?.name}`);\n      // MediaSource listeners are arrow functions with a lexical scope, and do not need to be bound\n      ms.addEventListener('sourceopen', this._onMediaSourceOpen);\n      ms.addEventListener('sourceended', this._onMediaSourceEnded);\n      ms.addEventListener('sourceclose', this._onMediaSourceClose);\n      if (this.appendSource) {\n        ms.addEventListener('startstreaming', this._onStartStreaming);\n        ms.addEventListener('endstreaming', this._onEndStreaming);\n      }\n\n      // cache the locally generated object url\n      const objectUrl = (this._objectUrl = self.URL.createObjectURL(ms));\n      // link video and media Source\n      if (this.appendSource) {\n        try {\n          media.removeAttribute('src');\n          // ManagedMediaSource will not open without disableRemotePlayback set to false or source alternatives\n          const MMS = (self as any).ManagedMediaSource;\n          media.disableRemotePlayback =\n            media.disableRemotePlayback || (MMS && ms instanceof MMS);\n          removeSourceChildren(media);\n          addSource(media, objectUrl);\n          media.load();\n        } catch (error) {\n          media.src = objectUrl;\n        }\n      } else {\n        media.src = objectUrl;\n      }\n      media.addEventListener('emptied', this._onMediaEmptied);\n    }\n  }\n  private _onEndStreaming = (event) => {\n    if (!this.hls) {\n      return;\n    }\n    this.hls.pauseBuffering();\n  };\n  private _onStartStreaming = (event) => {\n    if (!this.hls) {\n      return;\n    }\n    this.hls.resumeBuffering();\n  };\n\n  protected onMediaDetaching() {\n    const { media, mediaSource, _objectUrl } = this;\n    if (mediaSource) {\n      this.log('media source detaching');\n      if (mediaSource.readyState === 'open') {\n        try {\n          // endOfStream could trigger exception if any sourcebuffer is in updating state\n          // we don't really care about checking sourcebuffer state here,\n          // as we are anyway detaching the MediaSource\n          // let's just avoid this exception to propagate\n          mediaSource.endOfStream();\n        } catch (err) {\n          this.warn(\n            `onMediaDetaching: ${err.message} while calling endOfStream`,\n          );\n        }\n      }\n      // Clean up the SourceBuffers by invoking onBufferReset\n      this.onBufferReset();\n      mediaSource.removeEventListener('sourceopen', this._onMediaSourceOpen);\n      mediaSource.removeEventListener('sourceended', this._onMediaSourceEnded);\n      mediaSource.removeEventListener('sourceclose', this._onMediaSourceClose);\n      if (this.appendSource) {\n        mediaSource.removeEventListener(\n          'startstreaming',\n          this._onStartStreaming,\n        );\n        mediaSource.removeEventListener('endstreaming', this._onEndStreaming);\n      }\n\n      // Detach properly the MediaSource from the HTMLMediaElement as\n      // suggested in https://github.com/w3c/media-source/issues/53.\n      if (media) {\n        media.removeEventListener('emptied', this._onMediaEmptied);\n        if (_objectUrl) {\n          self.URL.revokeObjectURL(_objectUrl);\n        }\n\n        // clean up video tag src only if it's our own url. some external libraries might\n        // hijack the video tag and change its 'src' without destroying the Hls instance first\n        if (this.mediaSrc === _objectUrl) {\n          media.removeAttribute('src');\n          if (this.appendSource) {\n            removeSourceChildren(media);\n          }\n          media.load();\n        } else {\n          this.warn(\n            'media|source.src was changed by a third party - skip cleanup',\n          );\n        }\n      }\n\n      this.mediaSource = null;\n      this.media = null;\n      this._objectUrl = null;\n      this.bufferCodecEventsExpected = this._bufferCodecEventsTotal;\n      this.pendingTracks = {};\n      this.tracks = {};\n    }\n\n    this.hls.trigger(Events.MEDIA_DETACHED, undefined);\n  }\n\n  protected onBufferReset() {\n    this.getSourceBufferTypes().forEach((type) => {\n      this.resetBuffer(type);\n    });\n    this._initSourceBuffer();\n  }\n\n  private resetBuffer(type: SourceBufferName) {\n    const sb = this.sourceBuffer[type];\n    try {\n      if (sb) {\n        this.removeBufferListeners(type);\n        // Synchronously remove the SB from the map before the next call in order to prevent an async function from\n        // accessing it\n        this.sourceBuffer[type] = undefined;\n        if (this.mediaSource?.sourceBuffers.length) {\n          this.mediaSource.removeSourceBuffer(sb);\n        }\n      }\n    } catch (err) {\n      this.warn(`onBufferReset ${type}`, err);\n    }\n  }\n\n  protected onBufferCodecs(\n    event: Events.BUFFER_CODECS,\n    data: BufferCodecsData,\n  ) {\n    const sourceBufferCount = this.getSourceBufferTypes().length;\n    const trackNames = Object.keys(data);\n    trackNames.forEach((trackName) => {\n      if (sourceBufferCount) {\n        // check if SourceBuffer codec needs to change\n        const track = this.tracks[trackName];\n        if (track && typeof track.buffer.changeType === 'function') {\n          const { id, codec, levelCodec, container, metadata } =\n            data[trackName];\n          const currentCodecFull = pickMostCompleteCodecName(\n            track.codec,\n            track.levelCodec,\n          );\n          const currentCodec = currentCodecFull?.replace(\n            VIDEO_CODEC_PROFILE_REPLACE,\n            '$1',\n          );\n          let trackCodec = pickMostCompleteCodecName(codec, levelCodec);\n          const nextCodec = trackCodec?.replace(\n            VIDEO_CODEC_PROFILE_REPLACE,\n            '$1',\n          );\n          if (trackCodec && currentCodec !== nextCodec) {\n            if (trackName.slice(0, 5) === 'audio') {\n              trackCodec = getCodecCompatibleName(\n                trackCodec,\n                this.appendSource,\n              );\n            }\n            const mimeType = `${container};codecs=${trackCodec}`;\n            this.appendChangeType(trackName, mimeType);\n            this.log(`switching codec ${currentCodecFull} to ${trackCodec}`);\n            this.tracks[trackName] = {\n              buffer: track.buffer,\n              codec,\n              container,\n              levelCodec,\n              metadata,\n              id,\n            };\n          }\n        }\n      } else {\n        // if source buffer(s) not created yet, appended buffer tracks in this.pendingTracks\n        this.pendingTracks[trackName] = data[trackName];\n      }\n    });\n\n    // if sourcebuffers already created, do nothing ...\n    if (sourceBufferCount) {\n      return;\n    }\n\n    const bufferCodecEventsExpected = Math.max(\n      this.bufferCodecEventsExpected - 1,\n      0,\n    );\n    if (this.bufferCodecEventsExpected !== bufferCodecEventsExpected) {\n      this.log(\n        `${bufferCodecEventsExpected} bufferCodec event(s) expected ${trackNames.join(\n          ',',\n        )}`,\n      );\n      this.bufferCodecEventsExpected = bufferCodecEventsExpected;\n    }\n    if (this.mediaSource && this.mediaSource.readyState === 'open') {\n      this.checkPendingTracks();\n    }\n  }\n\n  protected appendChangeType(type, mimeType) {\n    const { operationQueue } = this;\n    const operation: BufferOperation = {\n      execute: () => {\n        const sb = this.sourceBuffer[type];\n        if (sb) {\n          this.log(`changing ${type} sourceBuffer type to ${mimeType}`);\n          sb.changeType(mimeType);\n        }\n        operationQueue.shiftAndExecuteNext(type);\n      },\n      onStart: () => {},\n      onComplete: () => {},\n      onError: (error: Error) => {\n        this.warn(`Failed to change ${type} SourceBuffer type`, error);\n      },\n    };\n\n    operationQueue.append(operation, type, !!this.pendingTracks[type]);\n  }\n\n  protected onBufferAppending(\n    event: Events.BUFFER_APPENDING,\n    eventData: BufferAppendingData,\n  ) {\n    const { hls, operationQueue, tracks } = this;\n    const { data, type, frag, part, chunkMeta } = eventData;\n    const chunkStats = chunkMeta.buffering[type];\n\n    const bufferAppendingStart = self.performance.now();\n    chunkStats.start = bufferAppendingStart;\n    const fragBuffering = frag.stats.buffering;\n    const partBuffering = part ? part.stats.buffering : null;\n    if (fragBuffering.start === 0) {\n      fragBuffering.start = bufferAppendingStart;\n    }\n    if (partBuffering && partBuffering.start === 0) {\n      partBuffering.start = bufferAppendingStart;\n    }\n\n    // TODO: Only update timestampOffset when audio/mpeg fragment or part is not contiguous with previously appended\n    // Adjusting `SourceBuffer.timestampOffset` (desired point in the timeline where the next frames should be appended)\n    // in Chrome browser when we detect MPEG audio container and time delta between level PTS and `SourceBuffer.timestampOffset`\n    // is greater than 100ms (this is enough to handle seek for VOD or level change for LIVE videos).\n    // More info here: https://github.com/video-dev/hls.js/issues/332#issuecomment-257986486\n    const audioTrack = tracks.audio;\n    let checkTimestampOffset = false;\n    if (type === 'audio' && audioTrack?.container === 'audio/mpeg') {\n      checkTimestampOffset =\n        !this.lastMpegAudioChunk ||\n        chunkMeta.id === 1 ||\n        this.lastMpegAudioChunk.sn !== chunkMeta.sn;\n      this.lastMpegAudioChunk = chunkMeta;\n    }\n\n    const fragStart = frag.start;\n    const operation: BufferOperation = {\n      execute: () => {\n        chunkStats.executeStart = self.performance.now();\n        if (checkTimestampOffset) {\n          const sb = this.sourceBuffer[type];\n          if (sb) {\n            const delta = fragStart - sb.timestampOffset;\n            if (Math.abs(delta) >= 0.1) {\n              this.log(\n                `Updating audio SourceBuffer timestampOffset to ${fragStart} (delta: ${delta}) sn: ${frag.sn})`,\n              );\n              sb.timestampOffset = fragStart;\n            }\n          }\n        }\n        this.appendExecutor(data, type);\n      },\n      onStart: () => {\n        // logger.debug(`[buffer-controller]: ${type} SourceBuffer updatestart`);\n      },\n      onComplete: () => {\n        // logger.debug(`[buffer-controller]: ${type} SourceBuffer updateend`);\n        const end = self.performance.now();\n        chunkStats.executeEnd = chunkStats.end = end;\n        if (fragBuffering.first === 0) {\n          fragBuffering.first = end;\n        }\n        if (partBuffering && partBuffering.first === 0) {\n          partBuffering.first = end;\n        }\n\n        const { sourceBuffer } = this;\n        const timeRanges = {};\n        for (const type in sourceBuffer) {\n          timeRanges[type] = BufferHelper.getBuffered(sourceBuffer[type]);\n        }\n        this.appendErrors[type] = 0;\n        if (type === 'audio' || type === 'video') {\n          this.appendErrors.audiovideo = 0;\n        } else {\n          this.appendErrors.audio = 0;\n          this.appendErrors.video = 0;\n        }\n        this.hls.trigger(Events.BUFFER_APPENDED, {\n          type,\n          frag,\n          part,\n          chunkMeta,\n          parent: frag.type,\n          timeRanges,\n        });\n      },\n      onError: (error: Error) => {\n        // in case any error occured while appending, put back segment in segments table\n        const event: ErrorData = {\n          type: ErrorTypes.MEDIA_ERROR,\n          parent: frag.type,\n          details: ErrorDetails.BUFFER_APPEND_ERROR,\n          sourceBufferName: type,\n          frag,\n          part,\n          chunkMeta,\n          error,\n          err: error,\n          fatal: false,\n        };\n\n        if ((error as DOMException).code === DOMException.QUOTA_EXCEEDED_ERR) {\n          // QuotaExceededError: http://www.w3.org/TR/html5/infrastructure.html#quotaexceedederror\n          // let's stop appending any segments, and report BUFFER_FULL_ERROR error\n          event.details = ErrorDetails.BUFFER_FULL_ERROR;\n        } else {\n          const appendErrorCount = ++this.appendErrors[type];\n          event.details = ErrorDetails.BUFFER_APPEND_ERROR;\n          /* with UHD content, we could get loop of quota exceeded error until\n            browser is able to evict some data from sourcebuffer. Retrying can help recover.\n          */\n          this.warn(\n            `Failed ${appendErrorCount}/${hls.config.appendErrorMaxRetry} times to append segment in \"${type}\" sourceBuffer`,\n          );\n          if (appendErrorCount >= hls.config.appendErrorMaxRetry) {\n            event.fatal = true;\n          }\n        }\n        hls.trigger(Events.ERROR, event);\n      },\n    };\n    operationQueue.append(operation, type, !!this.pendingTracks[type]);\n  }\n\n  protected onBufferFlushing(\n    event: Events.BUFFER_FLUSHING,\n    data: BufferFlushingData,\n  ) {\n    const { operationQueue } = this;\n    const flushOperation = (type: SourceBufferName): BufferOperation => ({\n      execute: this.removeExecutor.bind(\n        this,\n        type,\n        data.startOffset,\n        data.endOffset,\n      ),\n      onStart: () => {\n        // logger.debug(`[buffer-controller]: Started flushing ${data.startOffset} -> ${data.endOffset} for ${type} Source Buffer`);\n      },\n      onComplete: () => {\n        // logger.debug(`[buffer-controller]: Finished flushing ${data.startOffset} -> ${data.endOffset} for ${type} Source Buffer`);\n        this.hls.trigger(Events.BUFFER_FLUSHED, { type });\n      },\n      onError: (error: Error) => {\n        this.warn(`Failed to remove from ${type} SourceBuffer`, error);\n      },\n    });\n\n    if (data.type) {\n      operationQueue.append(flushOperation(data.type), data.type);\n    } else {\n      this.getSourceBufferTypes().forEach((type: SourceBufferName) => {\n        operationQueue.append(flushOperation(type), type);\n      });\n    }\n  }\n\n  protected onFragParsed(event: Events.FRAG_PARSED, data: FragParsedData) {\n    const { frag, part } = data;\n    const buffersAppendedTo: Array<SourceBufferName> = [];\n    const elementaryStreams = part\n      ? part.elementaryStreams\n      : frag.elementaryStreams;\n    if (elementaryStreams[ElementaryStreamTypes.AUDIOVIDEO]) {\n      buffersAppendedTo.push('audiovideo');\n    } else {\n      if (elementaryStreams[ElementaryStreamTypes.AUDIO]) {\n        buffersAppendedTo.push('audio');\n      }\n      if (elementaryStreams[ElementaryStreamTypes.VIDEO]) {\n        buffersAppendedTo.push('video');\n      }\n    }\n\n    const onUnblocked = () => {\n      const now = self.performance.now();\n      frag.stats.buffering.end = now;\n      if (part) {\n        part.stats.buffering.end = now;\n      }\n      const stats = part ? part.stats : frag.stats;\n      this.hls.trigger(Events.FRAG_BUFFERED, {\n        frag,\n        part,\n        stats,\n        id: frag.type,\n      });\n    };\n\n    if (buffersAppendedTo.length === 0) {\n      this.warn(\n        `Fragments must have at least one ElementaryStreamType set. type: ${frag.type} level: ${frag.level} sn: ${frag.sn}`,\n      );\n    }\n\n    this.blockBuffers(onUnblocked, buffersAppendedTo);\n  }\n\n  private onFragChanged(event: Events.FRAG_CHANGED, data: FragChangedData) {\n    this.trimBuffers();\n  }\n\n  // on BUFFER_EOS mark matching sourcebuffer(s) as ended and trigger checkEos()\n  // an undefined data.type will mark all buffers as EOS.\n  protected onBufferEos(event: Events.BUFFER_EOS, data: BufferEOSData) {\n    const ended = this.getSourceBufferTypes().reduce((acc, type) => {\n      const sb = this.sourceBuffer[type];\n      if (sb && (!data.type || data.type === type)) {\n        sb.ending = true;\n        if (!sb.ended) {\n          sb.ended = true;\n          this.log(`${type} sourceBuffer now EOS`);\n        }\n      }\n      return acc && !!(!sb || sb.ended);\n    }, true);\n\n    if (ended) {\n      this.log(`Queueing mediaSource.endOfStream()`);\n      this.blockBuffers(() => {\n        this.getSourceBufferTypes().forEach((type) => {\n          const sb = this.sourceBuffer[type];\n          if (sb) {\n            sb.ending = false;\n          }\n        });\n        const { mediaSource } = this;\n        if (!mediaSource || mediaSource.readyState !== 'open') {\n          if (mediaSource) {\n            this.log(\n              `Could not call mediaSource.endOfStream(). mediaSource.readyState: ${mediaSource.readyState}`,\n            );\n          }\n          return;\n        }\n        this.log(`Calling mediaSource.endOfStream()`);\n        // Allow this to throw and be caught by the enqueueing function\n        mediaSource.endOfStream();\n      });\n    }\n  }\n\n  protected onLevelUpdated(\n    event: Events.LEVEL_UPDATED,\n    { details }: LevelUpdatedData,\n  ) {\n    if (!details.fragments.length) {\n      return;\n    }\n    this.details = details;\n\n    if (this.getSourceBufferTypes().length) {\n      this.blockBuffers(this.updateMediaElementDuration.bind(this));\n    } else {\n      this.updateMediaElementDuration();\n    }\n  }\n\n  trimBuffers() {\n    const { hls, details, media } = this;\n    if (!media || details === null) {\n      return;\n    }\n\n    const sourceBufferTypes = this.getSourceBufferTypes();\n    if (!sourceBufferTypes.length) {\n      return;\n    }\n\n    const config: Readonly<HlsConfig> = hls.config;\n    const currentTime = media.currentTime;\n    const targetDuration = details.levelTargetDuration;\n\n    // Support for deprecated liveBackBufferLength\n    const backBufferLength =\n      details.live && config.liveBackBufferLength !== null\n        ? config.liveBackBufferLength\n        : config.backBufferLength;\n\n    if (Number.isFinite(backBufferLength) && backBufferLength > 0) {\n      const maxBackBufferLength = Math.max(backBufferLength, targetDuration);\n      const targetBackBufferPosition =\n        Math.floor(currentTime / targetDuration) * targetDuration -\n        maxBackBufferLength;\n\n      this.flushBackBuffer(\n        currentTime,\n        targetDuration,\n        targetBackBufferPosition,\n      );\n    }\n\n    if (\n      Number.isFinite(config.frontBufferFlushThreshold) &&\n      config.frontBufferFlushThreshold > 0\n    ) {\n      const frontBufferLength = Math.max(\n        config.maxBufferLength,\n        config.frontBufferFlushThreshold,\n      );\n\n      const maxFrontBufferLength = Math.max(frontBufferLength, targetDuration);\n      const targetFrontBufferPosition =\n        Math.floor(currentTime / targetDuration) * targetDuration +\n        maxFrontBufferLength;\n\n      this.flushFrontBuffer(\n        currentTime,\n        targetDuration,\n        targetFrontBufferPosition,\n      );\n    }\n  }\n\n  flushBackBuffer(\n    currentTime: number,\n    targetDuration: number,\n    targetBackBufferPosition: number,\n  ) {\n    const { details, sourceBuffer } = this;\n    const sourceBufferTypes = this.getSourceBufferTypes();\n\n    sourceBufferTypes.forEach((type: SourceBufferName) => {\n      const sb = sourceBuffer[type];\n      if (sb) {\n        const buffered = BufferHelper.getBuffered(sb);\n        // when target buffer start exceeds actual buffer start\n        if (\n          buffered.length > 0 &&\n          targetBackBufferPosition > buffered.start(0)\n        ) {\n          this.hls.trigger(Events.BACK_BUFFER_REACHED, {\n            bufferEnd: targetBackBufferPosition,\n          });\n\n          // Support for deprecated event:\n          if (details?.live) {\n            this.hls.trigger(Events.LIVE_BACK_BUFFER_REACHED, {\n              bufferEnd: targetBackBufferPosition,\n            });\n          } else if (\n            sb.ended &&\n            buffered.end(buffered.length - 1) - currentTime < targetDuration * 2\n          ) {\n            this.log(\n              `Cannot flush ${type} back buffer while SourceBuffer is in ended state`,\n            );\n            return;\n          }\n\n          this.hls.trigger(Events.BUFFER_FLUSHING, {\n            startOffset: 0,\n            endOffset: targetBackBufferPosition,\n            type,\n          });\n        }\n      }\n    });\n  }\n\n  flushFrontBuffer(\n    currentTime: number,\n    targetDuration: number,\n    targetFrontBufferPosition: number,\n  ) {\n    const { sourceBuffer } = this;\n    const sourceBufferTypes = this.getSourceBufferTypes();\n\n    sourceBufferTypes.forEach((type: SourceBufferName) => {\n      const sb = sourceBuffer[type];\n      if (sb) {\n        const buffered = BufferHelper.getBuffered(sb);\n        const numBufferedRanges = buffered.length;\n        // The buffer is either empty or contiguous\n        if (numBufferedRanges < 2) {\n          return;\n        }\n        const bufferStart = buffered.start(numBufferedRanges - 1);\n        const bufferEnd = buffered.end(numBufferedRanges - 1);\n        // No flush if we can tolerate the current buffer length or the current buffer range we would flush is contiguous with current position\n        if (\n          targetFrontBufferPosition > bufferStart ||\n          (currentTime >= bufferStart && currentTime <= bufferEnd)\n        ) {\n          return;\n        } else if (sb.ended && currentTime - bufferEnd < 2 * targetDuration) {\n          this.log(\n            `Cannot flush ${type} front buffer while SourceBuffer is in ended state`,\n          );\n          return;\n        }\n\n        this.hls.trigger(Events.BUFFER_FLUSHING, {\n          startOffset: bufferStart,\n          endOffset: Infinity,\n          type,\n        });\n      }\n    });\n  }\n\n  /**\n   * Update Media Source duration to current level duration or override to Infinity if configuration parameter\n   * 'liveDurationInfinity` is set to `true`\n   * More details: https://github.com/video-dev/hls.js/issues/355\n   */\n  private updateMediaElementDuration() {\n    if (\n      !this.details ||\n      !this.media ||\n      !this.mediaSource ||\n      this.mediaSource.readyState !== 'open'\n    ) {\n      return;\n    }\n    const { details, hls, media, mediaSource } = this;\n    const levelDuration = details.fragments[0].start + details.totalduration;\n    const mediaDuration = media.duration;\n    const msDuration = Number.isFinite(mediaSource.duration)\n      ? mediaSource.duration\n      : 0;\n\n    if (details.live && hls.config.liveDurationInfinity) {\n      // Override duration to Infinity\n      mediaSource.duration = Infinity;\n      this.updateSeekableRange(details);\n    } else if (\n      (levelDuration > msDuration && levelDuration > mediaDuration) ||\n      !Number.isFinite(mediaDuration)\n    ) {\n      // levelDuration was the last value we set.\n      // not using mediaSource.duration as the browser may tweak this value\n      // only update Media Source duration if its value increase, this is to avoid\n      // flushing already buffered portion when switching between quality level\n      this.log(`Updating Media Source duration to ${levelDuration.toFixed(3)}`);\n      mediaSource.duration = levelDuration;\n    }\n  }\n\n  updateSeekableRange(levelDetails) {\n    const mediaSource = this.mediaSource;\n    const fragments = levelDetails.fragments;\n    const len = fragments.length;\n    if (len && levelDetails.live && mediaSource?.setLiveSeekableRange) {\n      const start = Math.max(0, fragments[0].start);\n      const end = Math.max(start, start + levelDetails.totalduration);\n      this.log(\n        `Media Source duration is set to ${mediaSource.duration}. Setting seekable range to ${start}-${end}.`,\n      );\n      mediaSource.setLiveSeekableRange(start, end);\n    }\n  }\n\n  protected checkPendingTracks() {\n    const { bufferCodecEventsExpected, operationQueue, pendingTracks } = this;\n\n    // Check if we've received all of the expected bufferCodec events. When none remain, create all the sourceBuffers at once.\n    // This is important because the MSE spec allows implementations to throw QuotaExceededErrors if creating new sourceBuffers after\n    // data has been appended to existing ones.\n    // 2 tracks is the max (one for audio, one for video). If we've reach this max go ahead and create the buffers.\n    const pendingTracksCount = Object.keys(pendingTracks).length;\n    if (\n      pendingTracksCount &&\n      (!bufferCodecEventsExpected ||\n        pendingTracksCount === 2 ||\n        'audiovideo' in pendingTracks)\n    ) {\n      // ok, let's create them now !\n      this.createSourceBuffers(pendingTracks);\n      this.pendingTracks = {};\n      // append any pending segments now !\n      const buffers = this.getSourceBufferTypes();\n      if (buffers.length) {\n        this.hls.trigger(Events.BUFFER_CREATED, { tracks: this.tracks });\n        buffers.forEach((type: SourceBufferName) => {\n          operationQueue.executeNext(type);\n        });\n      } else {\n        const error = new Error(\n          'could not create source buffer for media codec(s)',\n        );\n        this.hls.trigger(Events.ERROR, {\n          type: ErrorTypes.MEDIA_ERROR,\n          details: ErrorDetails.BUFFER_INCOMPATIBLE_CODECS_ERROR,\n          fatal: true,\n          error,\n          reason: error.message,\n        });\n      }\n    }\n  }\n\n  protected createSourceBuffers(tracks: TrackSet) {\n    const { sourceBuffer, mediaSource } = this;\n    if (!mediaSource) {\n      throw Error('createSourceBuffers called when mediaSource was null');\n    }\n    for (const trackName in tracks) {\n      if (!sourceBuffer[trackName]) {\n        const track = tracks[trackName as keyof TrackSet];\n        if (!track) {\n          throw Error(\n            `source buffer exists for track ${trackName}, however track does not`,\n          );\n        }\n        // use levelCodec as first priority unless it contains multiple comma-separated codec values\n        let codec =\n          track.levelCodec?.indexOf(',') === -1\n            ? track.levelCodec\n            : track.codec;\n        if (codec) {\n          if (trackName.slice(0, 5) === 'audio') {\n            codec = getCodecCompatibleName(codec, this.appendSource);\n          }\n        }\n        const mimeType = `${track.container};codecs=${codec}`;\n        this.log(`creating sourceBuffer(${mimeType})`);\n        try {\n          const sb = (sourceBuffer[trackName] =\n            mediaSource.addSourceBuffer(mimeType));\n          const sbName = trackName as SourceBufferName;\n          this.addBufferListener(sbName, 'updatestart', this._onSBUpdateStart);\n          this.addBufferListener(sbName, 'updateend', this._onSBUpdateEnd);\n          this.addBufferListener(sbName, 'error', this._onSBUpdateError);\n          // ManagedSourceBuffer bufferedchange event\n          if (this.appendSource) {\n            this.addBufferListener(\n              sbName,\n              'bufferedchange',\n              (type: SourceBufferName, event: BufferedChangeEvent) => {\n                // If media was ejected check for a change. Added ranges are redundant with changes on 'updateend' event.\n                const removedRanges = event.removedRanges;\n                if (removedRanges?.length) {\n                  this.hls.trigger(Events.BUFFER_FLUSHED, {\n                    type: trackName as SourceBufferName,\n                  });\n                }\n              },\n            );\n          }\n\n          this.tracks[trackName] = {\n            buffer: sb,\n            codec: codec,\n            container: track.container,\n            levelCodec: track.levelCodec,\n            metadata: track.metadata,\n            id: track.id,\n          };\n        } catch (err) {\n          this.error(`error while trying to add sourceBuffer: ${err.message}`);\n          this.hls.trigger(Events.ERROR, {\n            type: ErrorTypes.MEDIA_ERROR,\n            details: ErrorDetails.BUFFER_ADD_CODEC_ERROR,\n            fatal: false,\n            error: err,\n            sourceBufferName: trackName as SourceBufferName,\n            mimeType: mimeType,\n          });\n        }\n      }\n    }\n  }\n\n  // Keep as arrow functions so that we can directly reference these functions directly as event listeners\n  private _onMediaSourceOpen = () => {\n    const { media, mediaSource } = this;\n    this.log('Media source opened');\n    if (media) {\n      media.removeEventListener('emptied', this._onMediaEmptied);\n      this.updateMediaElementDuration();\n      this.hls.trigger(Events.MEDIA_ATTACHED, {\n        media,\n        mediaSource: mediaSource as MediaSource,\n      });\n    }\n\n    if (mediaSource) {\n      // once received, don't listen anymore to sourceopen event\n      mediaSource.removeEventListener('sourceopen', this._onMediaSourceOpen);\n    }\n    this.checkPendingTracks();\n  };\n\n  private _onMediaSourceClose = () => {\n    this.log('Media source closed');\n  };\n\n  private _onMediaSourceEnded = () => {\n    this.log('Media source ended');\n  };\n\n  private _onMediaEmptied = () => {\n    const { mediaSrc, _objectUrl } = this;\n    if (mediaSrc !== _objectUrl) {\n      logger.error(\n        `Media element src was set while attaching MediaSource (${_objectUrl} > ${mediaSrc})`,\n      );\n    }\n  };\n\n  private get mediaSrc(): string | undefined {\n    const media = this.media?.querySelector?.('source') || this.media;\n    return media?.src;\n  }\n\n  private _onSBUpdateStart(type: SourceBufferName) {\n    const { operationQueue } = this;\n    const operation = operationQueue.current(type);\n    operation.onStart();\n  }\n\n  private _onSBUpdateEnd(type: SourceBufferName) {\n    if (this.mediaSource?.readyState === 'closed') {\n      this.resetBuffer(type);\n      return;\n    }\n    const { operationQueue } = this;\n    const operation = operationQueue.current(type);\n    operation.onComplete();\n    operationQueue.shiftAndExecuteNext(type);\n  }\n\n  private _onSBUpdateError(type: SourceBufferName, event: Event) {\n    const error = new Error(\n      `${type} SourceBuffer error. MediaSource readyState: ${this.mediaSource?.readyState}`,\n    );\n    this.error(`${error}`, event);\n    // according to http://www.w3.org/TR/media-source/#sourcebuffer-append-error\n    // SourceBuffer errors are not necessarily fatal; if so, the HTMLMediaElement will fire an error event\n    this.hls.trigger(Events.ERROR, {\n      type: ErrorTypes.MEDIA_ERROR,\n      details: ErrorDetails.BUFFER_APPENDING_ERROR,\n      sourceBufferName: type,\n      error,\n      fatal: false,\n    });\n    // updateend is always fired after error, so we'll allow that to shift the current operation off of the queue\n    const operation = this.operationQueue.current(type);\n    if (operation) {\n      operation.onError(error);\n    }\n  }\n\n  // This method must result in an updateend event; if remove is not called, _onSBUpdateEnd must be called manually\n  private removeExecutor(\n    type: SourceBufferName,\n    startOffset: number,\n    endOffset: number,\n  ) {\n    const { media, mediaSource, operationQueue, sourceBuffer } = this;\n    const sb = sourceBuffer[type];\n    if (!media || !mediaSource || !sb) {\n      this.warn(\n        `Attempting to remove from the ${type} SourceBuffer, but it does not exist`,\n      );\n      operationQueue.shiftAndExecuteNext(type);\n      return;\n    }\n    const mediaDuration = Number.isFinite(media.duration)\n      ? media.duration\n      : Infinity;\n    const msDuration = Number.isFinite(mediaSource.duration)\n      ? mediaSource.duration\n      : Infinity;\n    const removeStart = Math.max(0, startOffset);\n    const removeEnd = Math.min(endOffset, mediaDuration, msDuration);\n    if (removeEnd > removeStart && (!sb.ending || sb.ended)) {\n      sb.ended = false;\n      this.log(\n        `Removing [${removeStart},${removeEnd}] from the ${type} SourceBuffer`,\n      );\n      sb.remove(removeStart, removeEnd);\n    } else {\n      // Cycle the queue\n      operationQueue.shiftAndExecuteNext(type);\n    }\n  }\n\n  // This method must result in an updateend event; if append is not called, _onSBUpdateEnd must be called manually\n  private appendExecutor(data: Uint8Array, type: SourceBufferName) {\n    const sb = this.sourceBuffer[type];\n    if (!sb) {\n      if (!this.pendingTracks[type]) {\n        throw new Error(\n          `Attempting to append to the ${type} SourceBuffer, but it does not exist`,\n        );\n      }\n      return;\n    }\n\n    sb.ended = false;\n    sb.appendBuffer(data);\n  }\n\n  // Enqueues an operation to each SourceBuffer queue which, upon execution, resolves a promise. When all promises\n  // resolve, the onUnblocked function is executed. Functions calling this method do not need to unblock the queue\n  // upon completion, since we already do it here\n  private blockBuffers(\n    onUnblocked: () => void,\n    buffers: Array<SourceBufferName> = this.getSourceBufferTypes(),\n  ) {\n    if (!buffers.length) {\n      this.log('Blocking operation requested, but no SourceBuffers exist');\n      Promise.resolve().then(onUnblocked);\n      return;\n    }\n    const { operationQueue } = this;\n\n    // logger.debug(`[buffer-controller]: Blocking ${buffers} SourceBuffer`);\n    const blockingOperations = buffers.map((type) =>\n      operationQueue.appendBlocker(type as SourceBufferName),\n    );\n    Promise.all(blockingOperations).then(() => {\n      // logger.debug(`[buffer-controller]: Blocking operation resolved; unblocking ${buffers} SourceBuffer`);\n      onUnblocked();\n      buffers.forEach((type) => {\n        const sb = this.sourceBuffer[type];\n        // Only cycle the queue if the SB is not updating. There's a bug in Chrome which sets the SB updating flag to\n        // true when changing the MediaSource duration (https://bugs.chromium.org/p/chromium/issues/detail?id=959359&can=2&q=mediasource%20duration)\n        // While this is a workaround, it's probably useful to have around\n        if (!sb?.updating) {\n          operationQueue.shiftAndExecuteNext(type);\n        }\n      });\n    });\n  }\n\n  private getSourceBufferTypes(): Array<SourceBufferName> {\n    return Object.keys(this.sourceBuffer) as Array<SourceBufferName>;\n  }\n\n  private addBufferListener(\n    type: SourceBufferName,\n    event: string,\n    fn: Function,\n  ) {\n    const buffer = this.sourceBuffer[type];\n    if (!buffer) {\n      return;\n    }\n    const listener = fn.bind(this, type);\n    this.listeners[type].push({ event, listener });\n    buffer.addEventListener(event, listener);\n  }\n\n  private removeBufferListeners(type: SourceBufferName) {\n    const buffer = this.sourceBuffer[type];\n    if (!buffer) {\n      return;\n    }\n    this.listeners[type].forEach((l) => {\n      buffer.removeEventListener(l.event, l.listener);\n    });\n  }\n}\n\nfunction removeSourceChildren(node: HTMLElement) {\n  const sourceChildren = node.querySelectorAll('source');\n  [].slice.call(sourceChildren).forEach((source) => {\n    node.removeChild(source);\n  });\n}\n\nfunction addSource(media: HTMLMediaElement, url: string) {\n  const source = self.document.createElement('source');\n  source.type = 'video/mp4';\n  source.src = url;\n  media.appendChild(source);\n}\n", "import OutputFilter from './output-filter';\nimport { logger } from '../utils/logger';\n\n/**\n *\n * This code was ported from the dash.js project at:\n *   https://github.com/Dash-Industry-Forum/dash.js/blob/development/externals/cea608-parser.js\n *   https://github.com/Dash-Industry-Forum/dash.js/commit/8269b26a761e0853bb21d78780ed945144ecdd4d#diff-71bc295a2d6b6b7093a1d3290d53a4b2\n *\n * The original copyright appears below:\n *\n * The copyright in this software is being made available under the BSD License,\n * included below. This software may be subject to other third party and contributor\n * rights, including patent rights, and no such rights are granted under this license.\n *\n * Copyright (c) 2015-2016, DASH Industry Forum.\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification,\n * are permitted provided that the following conditions are met:\n *  1. Redistributions of source code must retain the above copyright notice, this\n *  list of conditions and the following disclaimer.\n *  * Redistributions in binary form must reproduce the above copyright notice,\n *  this list of conditions and the following disclaimer in the documentation and/or\n *  other materials provided with the distribution.\n *  2. Neither the name of Dash Industry Forum nor the names of its\n *  contributors may be used to endorse or promote products derived from this software\n *  without specific prior written permission.\n *\n *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY\n *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n *  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\n *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n *  POSSIBILITY OF SUCH DAMAGE.\n */\n/**\n *  Exceptions from regular ASCII. CodePoints are mapped to UTF-16 codes\n */\n\nconst specialCea608CharsCodes = {\n  0x2a: 0xe1, // lowercase a, acute accent\n  0x5c: 0xe9, // lowercase e, acute accent\n  0x5e: 0xed, // lowercase i, acute accent\n  0x5f: 0xf3, // lowercase o, acute accent\n  0x60: 0xfa, // lowercase u, acute accent\n  0x7b: 0xe7, // lowercase c with cedilla\n  0x7c: 0xf7, // division symbol\n  0x7d: 0xd1, // uppercase N tilde\n  0x7e: 0xf1, // lowercase n tilde\n  0x7f: 0x2588, // Full block\n  // THIS BLOCK INCLUDES THE 16 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS\n  // THAT COME FROM HI BYTE=0x11 AND LOW BETWEEN 0x30 AND 0x3F\n  // THIS MEANS THAT \\x50 MUST BE ADDED TO THE VALUES\n  0x80: 0xae, // Registered symbol (R)\n  0x81: 0xb0, // degree sign\n  0x82: 0xbd, // 1/2 symbol\n  0x83: 0xbf, // Inverted (open) question mark\n  0x84: 0x2122, // Trademark symbol (TM)\n  0x85: 0xa2, // Cents symbol\n  0x86: 0xa3, // Pounds sterling\n  0x87: 0x266a, // Music 8'th note\n  0x88: 0xe0, // lowercase a, grave accent\n  0x89: 0x20, // transparent space (regular)\n  0x8a: 0xe8, // lowercase e, grave accent\n  0x8b: 0xe2, // lowercase a, circumflex accent\n  0x8c: 0xea, // lowercase e, circumflex accent\n  0x8d: 0xee, // lowercase i, circumflex accent\n  0x8e: 0xf4, // lowercase o, circumflex accent\n  0x8f: 0xfb, // lowercase u, circumflex accent\n  // THIS BLOCK INCLUDES THE 32 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS\n  // THAT COME FROM HI BYTE=0x12 AND LOW BETWEEN 0x20 AND 0x3F\n  0x90: 0xc1, // capital letter A with acute\n  0x91: 0xc9, // capital letter E with acute\n  0x92: 0xd3, // capital letter O with acute\n  0x93: 0xda, // capital letter U with acute\n  0x94: 0xdc, // capital letter U with diaresis\n  0x95: 0xfc, // lowercase letter U with diaeresis\n  0x96: 0x2018, // opening single quote\n  0x97: 0xa1, // inverted exclamation mark\n  0x98: 0x2a, // asterisk\n  0x99: 0x2019, // closing single quote\n  0x9a: 0x2501, // box drawings heavy horizontal\n  0x9b: 0xa9, // copyright sign\n  0x9c: 0x2120, // Service mark\n  0x9d: 0x2022, // (round) bullet\n  0x9e: 0x201c, // Left double quotation mark\n  0x9f: 0x201d, // Right double quotation mark\n  0xa0: 0xc0, // uppercase A, grave accent\n  0xa1: 0xc2, // uppercase A, circumflex\n  0xa2: 0xc7, // uppercase C with cedilla\n  0xa3: 0xc8, // uppercase E, grave accent\n  0xa4: 0xca, // uppercase E, circumflex\n  0xa5: 0xcb, // capital letter E with diaresis\n  0xa6: 0xeb, // lowercase letter e with diaresis\n  0xa7: 0xce, // uppercase I, circumflex\n  0xa8: 0xcf, // uppercase I, with diaresis\n  0xa9: 0xef, // lowercase i, with diaresis\n  0xaa: 0xd4, // uppercase O, circumflex\n  0xab: 0xd9, // uppercase U, grave accent\n  0xac: 0xf9, // lowercase u, grave accent\n  0xad: 0xdb, // uppercase U, circumflex\n  0xae: 0xab, // left-pointing double angle quotation mark\n  0xaf: 0xbb, // right-pointing double angle quotation mark\n  // THIS BLOCK INCLUDES THE 32 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS\n  // THAT COME FROM HI BYTE=0x13 AND LOW BETWEEN 0x20 AND 0x3F\n  0xb0: 0xc3, // Uppercase A, tilde\n  0xb1: 0xe3, // Lowercase a, tilde\n  0xb2: 0xcd, // Uppercase I, acute accent\n  0xb3: 0xcc, // Uppercase I, grave accent\n  0xb4: 0xec, // Lowercase i, grave accent\n  0xb5: 0xd2, // Uppercase O, grave accent\n  0xb6: 0xf2, // Lowercase o, grave accent\n  0xb7: 0xd5, // Uppercase O, tilde\n  0xb8: 0xf5, // Lowercase o, tilde\n  0xb9: 0x7b, // Open curly brace\n  0xba: 0x7d, // Closing curly brace\n  0xbb: 0x5c, // Backslash\n  0xbc: 0x5e, // Caret\n  0xbd: 0x5f, // Underscore\n  0xbe: 0x7c, // Pipe (vertical line)\n  0xbf: 0x223c, // Tilde operator\n  0xc0: 0xc4, // Uppercase A, umlaut\n  0xc1: 0xe4, // Lowercase A, umlaut\n  0xc2: 0xd6, // Uppercase O, umlaut\n  0xc3: 0xf6, // Lowercase o, umlaut\n  0xc4: 0xdf, // Esszett (sharp S)\n  0xc5: 0xa5, // Yen symbol\n  0xc6: 0xa4, // Generic currency sign\n  0xc7: 0x2503, // Box drawings heavy vertical\n  0xc8: 0xc5, // Uppercase A, ring\n  0xc9: 0xe5, // Lowercase A, ring\n  0xca: 0xd8, // Uppercase O, stroke\n  0xcb: 0xf8, // Lowercase o, strok\n  0xcc: 0x250f, // Box drawings heavy down and right\n  0xcd: 0x2513, // Box drawings heavy down and left\n  0xce: 0x2517, // Box drawings heavy up and right\n  0xcf: 0x251b, // Box drawings heavy up and left\n};\n\n/**\n * Utils\n */\nconst getCharForByte = (byte: number) =>\n  String.fromCharCode(specialCea608CharsCodes[byte] || byte);\n\nconst NR_ROWS = 15;\nconst NR_COLS = 100;\n// Tables to look up row from PAC data\nconst rowsLowCh1 = {\n  0x11: 1,\n  0x12: 3,\n  0x15: 5,\n  0x16: 7,\n  0x17: 9,\n  0x10: 11,\n  0x13: 12,\n  0x14: 14,\n};\nconst rowsHighCh1 = {\n  0x11: 2,\n  0x12: 4,\n  0x15: 6,\n  0x16: 8,\n  0x17: 10,\n  0x13: 13,\n  0x14: 15,\n};\nconst rowsLowCh2 = {\n  0x19: 1,\n  0x1a: 3,\n  0x1d: 5,\n  0x1e: 7,\n  0x1f: 9,\n  0x18: 11,\n  0x1b: 12,\n  0x1c: 14,\n};\nconst rowsHighCh2 = {\n  0x19: 2,\n  0x1a: 4,\n  0x1d: 6,\n  0x1e: 8,\n  0x1f: 10,\n  0x1b: 13,\n  0x1c: 15,\n};\n\nconst backgroundColors = [\n  'white',\n  'green',\n  'blue',\n  'cyan',\n  'red',\n  'yellow',\n  'magenta',\n  'black',\n  'transparent',\n];\n\nconst enum VerboseLevel {\n  ERROR = 0,\n  TEXT = 1,\n  WARNING = 2,\n  INFO = 2,\n  DEBUG = 3,\n  DATA = 3,\n}\n\nclass CaptionsLogger {\n  public time: number | null = null;\n  public verboseLevel: VerboseLevel = VerboseLevel.ERROR;\n\n  log(severity: VerboseLevel, msg: string | (() => string)): void {\n    if (this.verboseLevel >= severity) {\n      const m: string = typeof msg === 'function' ? msg() : msg;\n      logger.log(`${this.time} [${severity}] ${m}`);\n    }\n  }\n}\n\nconst numArrayToHexArray = function (numArray: number[]): string[] {\n  const hexArray: string[] = [];\n  for (let j = 0; j < numArray.length; j++) {\n    hexArray.push(numArray[j].toString(16));\n  }\n\n  return hexArray;\n};\n\ntype PenStyles = {\n  foreground: string | null;\n  underline: boolean;\n  italics: boolean;\n  background: string;\n  flash: boolean;\n};\n\nclass PenState {\n  public foreground: string = 'white';\n  public underline: boolean = false;\n  public italics: boolean = false;\n  public background: string = 'black';\n  public flash: boolean = false;\n\n  reset() {\n    this.foreground = 'white';\n    this.underline = false;\n    this.italics = false;\n    this.background = 'black';\n    this.flash = false;\n  }\n\n  setStyles(styles: Partial<PenStyles>) {\n    const attribs = [\n      'foreground',\n      'underline',\n      'italics',\n      'background',\n      'flash',\n    ];\n    for (let i = 0; i < attribs.length; i++) {\n      const style = attribs[i];\n      if (styles.hasOwnProperty(style)) {\n        this[style] = styles[style];\n      }\n    }\n  }\n\n  isDefault() {\n    return (\n      this.foreground === 'white' &&\n      !this.underline &&\n      !this.italics &&\n      this.background === 'black' &&\n      !this.flash\n    );\n  }\n\n  equals(other: PenState) {\n    return (\n      this.foreground === other.foreground &&\n      this.underline === other.underline &&\n      this.italics === other.italics &&\n      this.background === other.background &&\n      this.flash === other.flash\n    );\n  }\n\n  copy(newPenState: PenState) {\n    this.foreground = newPenState.foreground;\n    this.underline = newPenState.underline;\n    this.italics = newPenState.italics;\n    this.background = newPenState.background;\n    this.flash = newPenState.flash;\n  }\n\n  toString(): string {\n    return (\n      'color=' +\n      this.foreground +\n      ', underline=' +\n      this.underline +\n      ', italics=' +\n      this.italics +\n      ', background=' +\n      this.background +\n      ', flash=' +\n      this.flash\n    );\n  }\n}\n\n/**\n * Unicode character with styling and background.\n * @constructor\n */\nclass StyledUnicodeChar {\n  uchar: string = ' ';\n  penState: PenState = new PenState();\n\n  reset() {\n    this.uchar = ' ';\n    this.penState.reset();\n  }\n\n  setChar(uchar: string, newPenState: PenState) {\n    this.uchar = uchar;\n    this.penState.copy(newPenState);\n  }\n\n  setPenState(newPenState: PenState) {\n    this.penState.copy(newPenState);\n  }\n\n  equals(other: StyledUnicodeChar) {\n    return this.uchar === other.uchar && this.penState.equals(other.penState);\n  }\n\n  copy(newChar: StyledUnicodeChar) {\n    this.uchar = newChar.uchar;\n    this.penState.copy(newChar.penState);\n  }\n\n  isEmpty(): boolean {\n    return this.uchar === ' ' && this.penState.isDefault();\n  }\n}\n\n/**\n * CEA-608 row consisting of NR_COLS instances of StyledUnicodeChar.\n * @constructor\n */\nexport class Row {\n  public chars: StyledUnicodeChar[] = [];\n  public pos: number = 0;\n  public currPenState: PenState = new PenState();\n  public cueStartTime: number | null = null;\n  private logger: CaptionsLogger;\n\n  constructor(logger: CaptionsLogger) {\n    for (let i = 0; i < NR_COLS; i++) {\n      this.chars.push(new StyledUnicodeChar());\n    }\n    this.logger = logger;\n  }\n\n  equals(other: Row) {\n    for (let i = 0; i < NR_COLS; i++) {\n      if (!this.chars[i].equals(other.chars[i])) {\n        return false;\n      }\n    }\n    return true;\n  }\n\n  copy(other: Row) {\n    for (let i = 0; i < NR_COLS; i++) {\n      this.chars[i].copy(other.chars[i]);\n    }\n  }\n\n  isEmpty(): boolean {\n    let empty = true;\n    for (let i = 0; i < NR_COLS; i++) {\n      if (!this.chars[i].isEmpty()) {\n        empty = false;\n        break;\n      }\n    }\n    return empty;\n  }\n\n  /**\n   *  Set the cursor to a valid column.\n   */\n  setCursor(absPos: number) {\n    if (this.pos !== absPos) {\n      this.pos = absPos;\n    }\n\n    if (this.pos < 0) {\n      this.logger.log(\n        VerboseLevel.DEBUG,\n        'Negative cursor position ' + this.pos,\n      );\n      this.pos = 0;\n    } else if (this.pos > NR_COLS) {\n      this.logger.log(\n        VerboseLevel.DEBUG,\n        'Too large cursor position ' + this.pos,\n      );\n      this.pos = NR_COLS;\n    }\n  }\n\n  /**\n   * Move the cursor relative to current position.\n   */\n  moveCursor(relPos: number) {\n    const newPos = this.pos + relPos;\n    if (relPos > 1) {\n      for (let i = this.pos + 1; i < newPos + 1; i++) {\n        this.chars[i].setPenState(this.currPenState);\n      }\n    }\n    this.setCursor(newPos);\n  }\n\n  /**\n   * Backspace, move one step back and clear character.\n   */\n  backSpace() {\n    this.moveCursor(-1);\n    this.chars[this.pos].setChar(' ', this.currPenState);\n  }\n\n  insertChar(byte: number) {\n    if (byte >= 0x90) {\n      // Extended char\n      this.backSpace();\n    }\n    const char = getCharForByte(byte);\n    if (this.pos >= NR_COLS) {\n      this.logger.log(\n        VerboseLevel.ERROR,\n        () =>\n          'Cannot insert ' +\n          byte.toString(16) +\n          ' (' +\n          char +\n          ') at position ' +\n          this.pos +\n          '. Skipping it!',\n      );\n      return;\n    }\n    this.chars[this.pos].setChar(char, this.currPenState);\n    this.moveCursor(1);\n  }\n\n  clearFromPos(startPos: number) {\n    let i: number;\n    for (i = startPos; i < NR_COLS; i++) {\n      this.chars[i].reset();\n    }\n  }\n\n  clear() {\n    this.clearFromPos(0);\n    this.pos = 0;\n    this.currPenState.reset();\n  }\n\n  clearToEndOfRow() {\n    this.clearFromPos(this.pos);\n  }\n\n  getTextString() {\n    const chars: string[] = [];\n    let empty = true;\n    for (let i = 0; i < NR_COLS; i++) {\n      const char = this.chars[i].uchar;\n      if (char !== ' ') {\n        empty = false;\n      }\n\n      chars.push(char);\n    }\n    if (empty) {\n      return '';\n    } else {\n      return chars.join('');\n    }\n  }\n\n  setPenStyles(styles: Partial<PenStyles>) {\n    this.currPenState.setStyles(styles);\n    const currChar = this.chars[this.pos];\n    currChar.setPenState(this.currPenState);\n  }\n}\n\n/**\n * Keep a CEA-608 screen of 32x15 styled characters\n * @constructor\n */\nexport class CaptionScreen {\n  rows: Row[] = [];\n  currRow: number = NR_ROWS - 1;\n  nrRollUpRows: number | null = null;\n  lastOutputScreen: CaptionScreen | null = null;\n  logger: CaptionsLogger;\n\n  constructor(logger: CaptionsLogger) {\n    for (let i = 0; i < NR_ROWS; i++) {\n      this.rows.push(new Row(logger));\n    }\n    this.logger = logger;\n  }\n\n  reset() {\n    for (let i = 0; i < NR_ROWS; i++) {\n      this.rows[i].clear();\n    }\n    this.currRow = NR_ROWS - 1;\n  }\n\n  equals(other: CaptionScreen): boolean {\n    let equal = true;\n    for (let i = 0; i < NR_ROWS; i++) {\n      if (!this.rows[i].equals(other.rows[i])) {\n        equal = false;\n        break;\n      }\n    }\n    return equal;\n  }\n\n  copy(other: CaptionScreen) {\n    for (let i = 0; i < NR_ROWS; i++) {\n      this.rows[i].copy(other.rows[i]);\n    }\n  }\n\n  isEmpty(): boolean {\n    let empty = true;\n    for (let i = 0; i < NR_ROWS; i++) {\n      if (!this.rows[i].isEmpty()) {\n        empty = false;\n        break;\n      }\n    }\n    return empty;\n  }\n\n  backSpace() {\n    const row = this.rows[this.currRow];\n    row.backSpace();\n  }\n\n  clearToEndOfRow() {\n    const row = this.rows[this.currRow];\n    row.clearToEndOfRow();\n  }\n\n  /**\n   * Insert a character (without styling) in the current row.\n   */\n  insertChar(char: number) {\n    const row = this.rows[this.currRow];\n    row.insertChar(char);\n  }\n\n  setPen(styles: Partial<PenStyles>) {\n    const row = this.rows[this.currRow];\n    row.setPenStyles(styles);\n  }\n\n  moveCursor(relPos: number) {\n    const row = this.rows[this.currRow];\n    row.moveCursor(relPos);\n  }\n\n  setCursor(absPos: number) {\n    this.logger.log(VerboseLevel.INFO, 'setCursor: ' + absPos);\n    const row = this.rows[this.currRow];\n    row.setCursor(absPos);\n  }\n\n  setPAC(pacData: PACData) {\n    this.logger.log(\n      VerboseLevel.INFO,\n      () => 'pacData = ' + JSON.stringify(pacData),\n    );\n    let newRow = pacData.row - 1;\n    if (this.nrRollUpRows && newRow < this.nrRollUpRows - 1) {\n      newRow = this.nrRollUpRows - 1;\n    }\n\n    // Make sure this only affects Roll-up Captions by checking this.nrRollUpRows\n    if (this.nrRollUpRows && this.currRow !== newRow) {\n      // clear all rows first\n      for (let i = 0; i < NR_ROWS; i++) {\n        this.rows[i].clear();\n      }\n\n      // Copy this.nrRollUpRows rows from lastOutputScreen and place it in the newRow location\n      // topRowIndex - the start of rows to copy (inclusive index)\n      const topRowIndex = this.currRow + 1 - this.nrRollUpRows;\n      // We only copy if the last position was already shown.\n      // We use the cueStartTime value to check this.\n      const lastOutputScreen = this.lastOutputScreen;\n      if (lastOutputScreen) {\n        const prevLineTime = lastOutputScreen.rows[topRowIndex].cueStartTime;\n        const time = this.logger.time;\n        if (prevLineTime !== null && time !== null && prevLineTime < time) {\n          for (let i = 0; i < this.nrRollUpRows; i++) {\n            this.rows[newRow - this.nrRollUpRows + i + 1].copy(\n              lastOutputScreen.rows[topRowIndex + i],\n            );\n          }\n        }\n      }\n    }\n\n    this.currRow = newRow;\n    const row = this.rows[this.currRow];\n    if (pacData.indent !== null) {\n      const indent = pacData.indent;\n      const prevPos = Math.max(indent - 1, 0);\n      row.setCursor(pacData.indent);\n      pacData.color = row.chars[prevPos].penState.foreground;\n    }\n    const styles: PenStyles = {\n      foreground: pacData.color,\n      underline: pacData.underline,\n      italics: pacData.italics,\n      background: 'black',\n      flash: false,\n    };\n    this.setPen(styles);\n  }\n\n  /**\n   * Set background/extra foreground, but first do back_space, and then insert space (backwards compatibility).\n   */\n  setBkgData(bkgData: Partial<PenStyles>) {\n    this.logger.log(\n      VerboseLevel.INFO,\n      () => 'bkgData = ' + JSON.stringify(bkgData),\n    );\n    this.backSpace();\n    this.setPen(bkgData);\n    this.insertChar(0x20); // Space\n  }\n\n  setRollUpRows(nrRows: number | null) {\n    this.nrRollUpRows = nrRows;\n  }\n\n  rollUp() {\n    if (this.nrRollUpRows === null) {\n      this.logger.log(\n        VerboseLevel.DEBUG,\n        'roll_up but nrRollUpRows not set yet',\n      );\n      return; // Not properly setup\n    }\n    this.logger.log(VerboseLevel.TEXT, () => this.getDisplayText());\n    const topRowIndex = this.currRow + 1 - this.nrRollUpRows;\n    const topRow = this.rows.splice(topRowIndex, 1)[0];\n    topRow.clear();\n    this.rows.splice(this.currRow, 0, topRow);\n    this.logger.log(VerboseLevel.INFO, 'Rolling up');\n    // this.logger.log(VerboseLevel.TEXT, this.get_display_text())\n  }\n\n  /**\n   * Get all non-empty rows with as unicode text.\n   */\n  getDisplayText(asOneRow?: boolean) {\n    asOneRow = asOneRow || false;\n    const displayText: string[] = [];\n    let text = '';\n    let rowNr = -1;\n    for (let i = 0; i < NR_ROWS; i++) {\n      const rowText = this.rows[i].getTextString();\n      if (rowText) {\n        rowNr = i + 1;\n        if (asOneRow) {\n          displayText.push('Row ' + rowNr + \": '\" + rowText + \"'\");\n        } else {\n          displayText.push(rowText.trim());\n        }\n      }\n    }\n    if (displayText.length > 0) {\n      if (asOneRow) {\n        text = '[' + displayText.join(' | ') + ']';\n      } else {\n        text = displayText.join('\\n');\n      }\n    }\n    return text;\n  }\n\n  getTextAndFormat() {\n    return this.rows;\n  }\n}\n\n// var modes = ['MODE_ROLL-UP', 'MODE_POP-ON', 'MODE_PAINT-ON', 'MODE_TEXT'];\n\ntype CaptionModes =\n  | 'MODE_ROLL-UP'\n  | 'MODE_POP-ON'\n  | 'MODE_PAINT-ON'\n  | 'MODE_TEXT'\n  | null;\n\nclass Cea608Channel {\n  chNr: number;\n  outputFilter: OutputFilter;\n  mode: CaptionModes;\n  verbose: number;\n  displayedMemory: CaptionScreen;\n  nonDisplayedMemory: CaptionScreen;\n  lastOutputScreen: CaptionScreen;\n  currRollUpRow: Row;\n  writeScreen: CaptionScreen;\n  cueStartTime: number | null;\n  logger: CaptionsLogger;\n\n  constructor(\n    channelNumber: number,\n    outputFilter: OutputFilter,\n    logger: CaptionsLogger,\n  ) {\n    this.chNr = channelNumber;\n    this.outputFilter = outputFilter;\n    this.mode = null;\n    this.verbose = 0;\n    this.displayedMemory = new CaptionScreen(logger);\n    this.nonDisplayedMemory = new CaptionScreen(logger);\n    this.lastOutputScreen = new CaptionScreen(logger);\n    this.currRollUpRow = this.displayedMemory.rows[NR_ROWS - 1];\n    this.writeScreen = this.displayedMemory;\n    this.mode = null;\n    this.cueStartTime = null; // Keeps track of where a cue started.\n    this.logger = logger;\n  }\n\n  reset() {\n    this.mode = null;\n    this.displayedMemory.reset();\n    this.nonDisplayedMemory.reset();\n    this.lastOutputScreen.reset();\n    this.outputFilter.reset();\n    this.currRollUpRow = this.displayedMemory.rows[NR_ROWS - 1];\n    this.writeScreen = this.displayedMemory;\n    this.mode = null;\n    this.cueStartTime = null;\n  }\n\n  getHandler(): OutputFilter {\n    return this.outputFilter;\n  }\n\n  setHandler(newHandler: OutputFilter) {\n    this.outputFilter = newHandler;\n  }\n\n  setPAC(pacData: PACData) {\n    this.writeScreen.setPAC(pacData);\n  }\n\n  setBkgData(bkgData: Partial<PenStyles>) {\n    this.writeScreen.setBkgData(bkgData);\n  }\n\n  setMode(newMode: CaptionModes) {\n    if (newMode === this.mode) {\n      return;\n    }\n\n    this.mode = newMode;\n    this.logger.log(VerboseLevel.INFO, () => 'MODE=' + newMode);\n    if (this.mode === 'MODE_POP-ON') {\n      this.writeScreen = this.nonDisplayedMemory;\n    } else {\n      this.writeScreen = this.displayedMemory;\n      this.writeScreen.reset();\n    }\n    if (this.mode !== 'MODE_ROLL-UP') {\n      this.displayedMemory.nrRollUpRows = null;\n      this.nonDisplayedMemory.nrRollUpRows = null;\n    }\n    this.mode = newMode;\n  }\n\n  insertChars(chars: number[]) {\n    for (let i = 0; i < chars.length; i++) {\n      this.writeScreen.insertChar(chars[i]);\n    }\n\n    const screen =\n      this.writeScreen === this.displayedMemory ? 'DISP' : 'NON_DISP';\n    this.logger.log(\n      VerboseLevel.INFO,\n      () => screen + ': ' + this.writeScreen.getDisplayText(true),\n    );\n    if (this.mode === 'MODE_PAINT-ON' || this.mode === 'MODE_ROLL-UP') {\n      this.logger.log(\n        VerboseLevel.TEXT,\n        () => 'DISPLAYED: ' + this.displayedMemory.getDisplayText(true),\n      );\n      this.outputDataUpdate();\n    }\n  }\n\n  ccRCL() {\n    // Resume Caption Loading (switch mode to Pop On)\n    this.logger.log(VerboseLevel.INFO, 'RCL - Resume Caption Loading');\n    this.setMode('MODE_POP-ON');\n  }\n\n  ccBS() {\n    // BackSpace\n    this.logger.log(VerboseLevel.INFO, 'BS - BackSpace');\n    if (this.mode === 'MODE_TEXT') {\n      return;\n    }\n\n    this.writeScreen.backSpace();\n    if (this.writeScreen === this.displayedMemory) {\n      this.outputDataUpdate();\n    }\n  }\n\n  ccAOF() {\n    // Reserved (formerly Alarm Off)\n  }\n\n  ccAON() {\n    // Reserved (formerly Alarm On)\n  }\n\n  ccDER() {\n    // Delete to End of Row\n    this.logger.log(VerboseLevel.INFO, 'DER- Delete to End of Row');\n    this.writeScreen.clearToEndOfRow();\n    this.outputDataUpdate();\n  }\n\n  ccRU(nrRows: number | null) {\n    // Roll-Up Captions-2,3,or 4 Rows\n    this.logger.log(VerboseLevel.INFO, 'RU(' + nrRows + ') - Roll Up');\n    this.writeScreen = this.displayedMemory;\n    this.setMode('MODE_ROLL-UP');\n    this.writeScreen.setRollUpRows(nrRows);\n  }\n\n  ccFON() {\n    // Flash On\n    this.logger.log(VerboseLevel.INFO, 'FON - Flash On');\n    this.writeScreen.setPen({ flash: true });\n  }\n\n  ccRDC() {\n    // Resume Direct Captioning (switch mode to PaintOn)\n    this.logger.log(VerboseLevel.INFO, 'RDC - Resume Direct Captioning');\n    this.setMode('MODE_PAINT-ON');\n  }\n\n  ccTR() {\n    // Text Restart in text mode (not supported, however)\n    this.logger.log(VerboseLevel.INFO, 'TR');\n    this.setMode('MODE_TEXT');\n  }\n\n  ccRTD() {\n    // Resume Text Display in Text mode (not supported, however)\n    this.logger.log(VerboseLevel.INFO, 'RTD');\n    this.setMode('MODE_TEXT');\n  }\n\n  ccEDM() {\n    // Erase Displayed Memory\n    this.logger.log(VerboseLevel.INFO, 'EDM - Erase Displayed Memory');\n    this.displayedMemory.reset();\n    this.outputDataUpdate(true);\n  }\n\n  ccCR() {\n    // Carriage Return\n    this.logger.log(VerboseLevel.INFO, 'CR - Carriage Return');\n    this.writeScreen.rollUp();\n    this.outputDataUpdate(true);\n  }\n\n  ccENM() {\n    // Erase Non-Displayed Memory\n    this.logger.log(VerboseLevel.INFO, 'ENM - Erase Non-displayed Memory');\n    this.nonDisplayedMemory.reset();\n  }\n\n  ccEOC() {\n    // End of Caption (Flip Memories)\n    this.logger.log(VerboseLevel.INFO, 'EOC - End Of Caption');\n    if (this.mode === 'MODE_POP-ON') {\n      const tmp = this.displayedMemory;\n      this.displayedMemory = this.nonDisplayedMemory;\n      this.nonDisplayedMemory = tmp;\n      this.writeScreen = this.nonDisplayedMemory;\n      this.logger.log(\n        VerboseLevel.TEXT,\n        () => 'DISP: ' + this.displayedMemory.getDisplayText(),\n      );\n    }\n    this.outputDataUpdate(true);\n  }\n\n  ccTO(nrCols: number) {\n    // Tab Offset 1,2, or 3 columns\n    this.logger.log(VerboseLevel.INFO, 'TO(' + nrCols + ') - Tab Offset');\n    this.writeScreen.moveCursor(nrCols);\n  }\n\n  ccMIDROW(secondByte: number) {\n    // Parse MIDROW command\n    const styles: Partial<PenStyles> = { flash: false };\n    styles.underline = secondByte % 2 === 1;\n    styles.italics = secondByte >= 0x2e;\n    if (!styles.italics) {\n      const colorIndex = Math.floor(secondByte / 2) - 0x10;\n      const colors = [\n        'white',\n        'green',\n        'blue',\n        'cyan',\n        'red',\n        'yellow',\n        'magenta',\n      ];\n      styles.foreground = colors[colorIndex];\n    } else {\n      styles.foreground = 'white';\n    }\n    this.logger.log(VerboseLevel.INFO, 'MIDROW: ' + JSON.stringify(styles));\n    this.writeScreen.setPen(styles);\n  }\n\n  outputDataUpdate(dispatch: boolean = false) {\n    const time = this.logger.time;\n    if (time === null) {\n      return;\n    }\n\n    if (this.outputFilter) {\n      if (this.cueStartTime === null && !this.displayedMemory.isEmpty()) {\n        // Start of a new cue\n        this.cueStartTime = time;\n      } else {\n        if (!this.displayedMemory.equals(this.lastOutputScreen)) {\n          this.outputFilter.newCue(\n            this.cueStartTime!,\n            time,\n            this.lastOutputScreen,\n          );\n          if (dispatch && this.outputFilter.dispatchCue) {\n            this.outputFilter.dispatchCue();\n          }\n\n          this.cueStartTime = this.displayedMemory.isEmpty() ? null : time;\n        }\n      }\n      this.lastOutputScreen.copy(this.displayedMemory);\n    }\n  }\n\n  cueSplitAtTime(t: number) {\n    if (this.outputFilter) {\n      if (!this.displayedMemory.isEmpty()) {\n        if (this.outputFilter.newCue) {\n          this.outputFilter.newCue(this.cueStartTime!, t, this.displayedMemory);\n        }\n\n        this.cueStartTime = t;\n      }\n    }\n  }\n}\n\ninterface PACData {\n  row: number;\n  indent: number | null;\n  color: string | null;\n  underline: boolean;\n  italics: boolean;\n}\n\ntype SupportedField = 1 | 3;\n\ntype Channels = 0 | 1 | 2; // Will be 1 or 2 when parsing captions\n\ntype CmdHistory = {\n  a: number | null;\n  b: number | null;\n};\n\nclass Cea608Parser {\n  channels: Array<Cea608Channel | null>;\n  currentChannel: Channels = 0;\n  cmdHistory: CmdHistory = createCmdHistory();\n  logger: CaptionsLogger;\n\n  constructor(field: SupportedField, out1: OutputFilter, out2: OutputFilter) {\n    const logger = (this.logger = new CaptionsLogger());\n    this.channels = [\n      null,\n      new Cea608Channel(field, out1, logger),\n      new Cea608Channel(field + 1, out2, logger),\n    ];\n  }\n\n  getHandler(channel: number) {\n    return (this.channels[channel] as Cea608Channel).getHandler();\n  }\n\n  setHandler(channel: number, newHandler: OutputFilter) {\n    (this.channels[channel] as Cea608Channel).setHandler(newHandler);\n  }\n\n  /**\n   * Add data for time t in forms of list of bytes (unsigned ints). The bytes are treated as pairs.\n   */\n  addData(time: number | null, byteList: number[]) {\n    this.logger.time = time;\n    for (let i = 0; i < byteList.length; i += 2) {\n      const a = byteList[i] & 0x7f;\n      const b = byteList[i + 1] & 0x7f;\n      let cmdFound: boolean = false;\n      let charsFound: number[] | null = null;\n\n      if (a === 0 && b === 0) {\n        continue;\n      } else {\n        this.logger.log(\n          VerboseLevel.DATA,\n          () =>\n            '[' +\n            numArrayToHexArray([byteList[i], byteList[i + 1]]) +\n            '] -> (' +\n            numArrayToHexArray([a, b]) +\n            ')',\n        );\n      }\n\n      const cmdHistory = this.cmdHistory;\n      const isControlCode = a >= 0x10 && a <= 0x1f;\n      if (isControlCode) {\n        // Skip redundant control codes\n        if (hasCmdRepeated(a, b, cmdHistory)) {\n          setLastCmd(null, null, cmdHistory);\n          this.logger.log(\n            VerboseLevel.DEBUG,\n            () =>\n              'Repeated command (' +\n              numArrayToHexArray([a, b]) +\n              ') is dropped',\n          );\n          continue;\n        }\n        setLastCmd(a, b, this.cmdHistory);\n\n        cmdFound = this.parseCmd(a, b);\n\n        if (!cmdFound) {\n          cmdFound = this.parseMidrow(a, b);\n        }\n\n        if (!cmdFound) {\n          cmdFound = this.parsePAC(a, b);\n        }\n\n        if (!cmdFound) {\n          cmdFound = this.parseBackgroundAttributes(a, b);\n        }\n      } else {\n        setLastCmd(null, null, cmdHistory);\n      }\n      if (!cmdFound) {\n        charsFound = this.parseChars(a, b);\n        if (charsFound) {\n          const currChNr = this.currentChannel;\n          if (currChNr && currChNr > 0) {\n            const channel = this.channels[currChNr] as Cea608Channel;\n            channel.insertChars(charsFound);\n          } else {\n            this.logger.log(\n              VerboseLevel.WARNING,\n              'No channel found yet. TEXT-MODE?',\n            );\n          }\n        }\n      }\n      if (!cmdFound && !charsFound) {\n        this.logger.log(\n          VerboseLevel.WARNING,\n          () =>\n            \"Couldn't parse cleaned data \" +\n            numArrayToHexArray([a, b]) +\n            ' orig: ' +\n            numArrayToHexArray([byteList[i], byteList[i + 1]]),\n        );\n      }\n    }\n  }\n\n  /**\n   * Parse Command.\n   * @returns True if a command was found\n   */\n  parseCmd(a: number, b: number): boolean {\n    const cond1 =\n      (a === 0x14 || a === 0x1c || a === 0x15 || a === 0x1d) &&\n      b >= 0x20 &&\n      b <= 0x2f;\n    const cond2 = (a === 0x17 || a === 0x1f) && b >= 0x21 && b <= 0x23;\n    if (!(cond1 || cond2)) {\n      return false;\n    }\n\n    const chNr = a === 0x14 || a === 0x15 || a === 0x17 ? 1 : 2;\n    const channel = this.channels[chNr] as Cea608Channel;\n\n    if (a === 0x14 || a === 0x15 || a === 0x1c || a === 0x1d) {\n      if (b === 0x20) {\n        channel.ccRCL();\n      } else if (b === 0x21) {\n        channel.ccBS();\n      } else if (b === 0x22) {\n        channel.ccAOF();\n      } else if (b === 0x23) {\n        channel.ccAON();\n      } else if (b === 0x24) {\n        channel.ccDER();\n      } else if (b === 0x25) {\n        channel.ccRU(2);\n      } else if (b === 0x26) {\n        channel.ccRU(3);\n      } else if (b === 0x27) {\n        channel.ccRU(4);\n      } else if (b === 0x28) {\n        channel.ccFON();\n      } else if (b === 0x29) {\n        channel.ccRDC();\n      } else if (b === 0x2a) {\n        channel.ccTR();\n      } else if (b === 0x2b) {\n        channel.ccRTD();\n      } else if (b === 0x2c) {\n        channel.ccEDM();\n      } else if (b === 0x2d) {\n        channel.ccCR();\n      } else if (b === 0x2e) {\n        channel.ccENM();\n      } else if (b === 0x2f) {\n        channel.ccEOC();\n      }\n    } else {\n      // a == 0x17 || a == 0x1F\n      channel.ccTO(b - 0x20);\n    }\n    this.currentChannel = chNr;\n    return true;\n  }\n\n  /**\n   * Parse midrow styling command\n   */\n  parseMidrow(a: number, b: number): boolean {\n    let chNr: number = 0;\n\n    if ((a === 0x11 || a === 0x19) && b >= 0x20 && b <= 0x2f) {\n      if (a === 0x11) {\n        chNr = 1;\n      } else {\n        chNr = 2;\n      }\n\n      if (chNr !== this.currentChannel) {\n        this.logger.log(\n          VerboseLevel.ERROR,\n          'Mismatch channel in midrow parsing',\n        );\n        return false;\n      }\n      const channel = this.channels[chNr];\n      if (!channel) {\n        return false;\n      }\n      channel.ccMIDROW(b);\n      this.logger.log(\n        VerboseLevel.DEBUG,\n        () => 'MIDROW (' + numArrayToHexArray([a, b]) + ')',\n      );\n      return true;\n    }\n    return false;\n  }\n\n  /**\n   * Parse Preable Access Codes (Table 53).\n   * @returns {Boolean} Tells if PAC found\n   */\n  parsePAC(a: number, b: number): boolean {\n    let row: number;\n\n    const case1 =\n      ((a >= 0x11 && a <= 0x17) || (a >= 0x19 && a <= 0x1f)) &&\n      b >= 0x40 &&\n      b <= 0x7f;\n    const case2 = (a === 0x10 || a === 0x18) && b >= 0x40 && b <= 0x5f;\n    if (!(case1 || case2)) {\n      return false;\n    }\n\n    const chNr: Channels = a <= 0x17 ? 1 : 2;\n\n    if (b >= 0x40 && b <= 0x5f) {\n      row = chNr === 1 ? rowsLowCh1[a] : rowsLowCh2[a];\n    } else {\n      // 0x60 <= b <= 0x7F\n      row = chNr === 1 ? rowsHighCh1[a] : rowsHighCh2[a];\n    }\n    const channel = this.channels[chNr];\n    if (!channel) {\n      return false;\n    }\n    channel.setPAC(this.interpretPAC(row, b));\n    this.currentChannel = chNr;\n    return true;\n  }\n\n  /**\n   * Interpret the second byte of the pac, and return the information.\n   * @returns pacData with style parameters\n   */\n  interpretPAC(row: number, byte: number): PACData {\n    let pacIndex;\n    const pacData: PACData = {\n      color: null,\n      italics: false,\n      indent: null,\n      underline: false,\n      row: row,\n    };\n\n    if (byte > 0x5f) {\n      pacIndex = byte - 0x60;\n    } else {\n      pacIndex = byte - 0x40;\n    }\n\n    pacData.underline = (pacIndex & 1) === 1;\n    if (pacIndex <= 0xd) {\n      pacData.color = [\n        'white',\n        'green',\n        'blue',\n        'cyan',\n        'red',\n        'yellow',\n        'magenta',\n        'white',\n      ][Math.floor(pacIndex / 2)];\n    } else if (pacIndex <= 0xf) {\n      pacData.italics = true;\n      pacData.color = 'white';\n    } else {\n      pacData.indent = Math.floor((pacIndex - 0x10) / 2) * 4;\n    }\n    return pacData; // Note that row has zero offset. The spec uses 1.\n  }\n\n  /**\n   * Parse characters.\n   * @returns An array with 1 to 2 codes corresponding to chars, if found. null otherwise.\n   */\n  parseChars(a: number, b: number): number[] | null {\n    let channelNr: Channels;\n    let charCodes: number[] | null = null;\n    let charCode1: number | null = null;\n\n    if (a >= 0x19) {\n      channelNr = 2;\n      charCode1 = a - 8;\n    } else {\n      channelNr = 1;\n      charCode1 = a;\n    }\n    if (charCode1 >= 0x11 && charCode1 <= 0x13) {\n      // Special character\n      let oneCode;\n      if (charCode1 === 0x11) {\n        oneCode = b + 0x50;\n      } else if (charCode1 === 0x12) {\n        oneCode = b + 0x70;\n      } else {\n        oneCode = b + 0x90;\n      }\n\n      this.logger.log(\n        VerboseLevel.INFO,\n        () =>\n          \"Special char '\" +\n          getCharForByte(oneCode) +\n          \"' in channel \" +\n          channelNr,\n      );\n      charCodes = [oneCode];\n    } else if (a >= 0x20 && a <= 0x7f) {\n      charCodes = b === 0 ? [a] : [a, b];\n    }\n    if (charCodes) {\n      this.logger.log(\n        VerboseLevel.DEBUG,\n        () =>\n          'Char codes =  ' +\n          numArrayToHexArray(charCodes as number[]).join(','),\n      );\n    }\n    return charCodes;\n  }\n\n  /**\n   * Parse extended background attributes as well as new foreground color black.\n   * @returns True if background attributes are found\n   */\n  parseBackgroundAttributes(a: number, b: number): boolean {\n    const case1 = (a === 0x10 || a === 0x18) && b >= 0x20 && b <= 0x2f;\n    const case2 = (a === 0x17 || a === 0x1f) && b >= 0x2d && b <= 0x2f;\n    if (!(case1 || case2)) {\n      return false;\n    }\n    let index: number;\n    const bkgData: Partial<PenStyles> = {};\n    if (a === 0x10 || a === 0x18) {\n      index = Math.floor((b - 0x20) / 2);\n      bkgData.background = backgroundColors[index];\n      if (b % 2 === 1) {\n        bkgData.background = bkgData.background + '_semi';\n      }\n    } else if (b === 0x2d) {\n      bkgData.background = 'transparent';\n    } else {\n      bkgData.foreground = 'black';\n      if (b === 0x2f) {\n        bkgData.underline = true;\n      }\n    }\n    const chNr: Channels = a <= 0x17 ? 1 : 2;\n    const channel: Cea608Channel = this.channels[chNr] as Cea608Channel;\n    channel.setBkgData(bkgData);\n    return true;\n  }\n\n  /**\n   * Reset state of parser and its channels.\n   */\n  reset() {\n    for (let i = 0; i < Object.keys(this.channels).length; i++) {\n      const channel = this.channels[i];\n      if (channel) {\n        channel.reset();\n      }\n    }\n    setLastCmd(null, null, this.cmdHistory);\n  }\n\n  /**\n   * Trigger the generation of a cue, and the start of a new one if displayScreens are not empty.\n   */\n  cueSplitAtTime(t: number) {\n    for (let i = 0; i < this.channels.length; i++) {\n      const channel = this.channels[i];\n      if (channel) {\n        channel.cueSplitAtTime(t);\n      }\n    }\n  }\n}\n\nfunction setLastCmd(\n  a: number | null,\n  b: number | null,\n  cmdHistory: CmdHistory,\n) {\n  cmdHistory.a = a;\n  cmdHistory.b = b;\n}\n\nfunction hasCmdRepeated(a: number, b: number, cmdHistory: CmdHistory) {\n  return cmdHistory.a === a && cmdHistory.b === b;\n}\n\nfunction createCmdHistory(): CmdHistory {\n  return {\n    a: null,\n    b: null,\n  };\n}\n\nexport default Cea608Parser;\n", "import type { TimelineController } from '../controller/timeline-controller';\nimport type { CaptionScreen } from './cea-608-parser';\n\nexport default class OutputFilter {\n  private timelineController: TimelineController;\n  private cueRanges: Array<[number, number]> = [];\n  private trackName: string;\n  private startTime: number | null = null;\n  private endTime: number | null = null;\n  private screen: CaptionScreen | null = null;\n\n  constructor(timelineController: TimelineController, trackName: string) {\n    this.timelineController = timelineController;\n    this.trackName = trackName;\n  }\n\n  dispatchCue() {\n    if (this.startTime === null) {\n      return;\n    }\n\n    this.timelineController.addCues(\n      this.trackName,\n      this.startTime,\n      this.endTime as number,\n      this.screen as CaptionScreen,\n      this.cueRanges,\n    );\n    this.startTime = null;\n  }\n\n  newCue(startTime: number, endTime: number, screen: CaptionScreen) {\n    if (this.startTime === null || this.startTime > startTime) {\n      this.startTime = startTime;\n    }\n\n    this.endTime = endTime;\n    this.screen = screen;\n    this.timelineController.createCaptionsTrack(this.trackName);\n  }\n\n  reset() {\n    this.cueRanges = [];\n    this.startTime = null;\n  }\n}\n", "/**\n * Copyright 2013 vtt.js Contributors\n *\n * Licensed under the Apache License, Version 2.0 (the 'License');\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an 'AS IS' BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { optionalSelf } from './global';\n\ndeclare interface VTTCuePolyfill extends VTTCue {\n  new (...args): VTTCuePolyfill;\n  hasBeenReset: boolean;\n  displayState: void;\n}\n\nexport default (function () {\n  if (optionalSelf?.VTTCue) {\n    return self.VTTCue;\n  }\n\n  const AllowedDirections = ['', 'lr', 'rl'] as const;\n  type Direction = (typeof AllowedDirections)[number];\n\n  const AllowedAlignments = [\n    'start',\n    'middle',\n    'end',\n    'left',\n    'right',\n  ] as const;\n  type Alignment = (typeof AllowedAlignments)[number];\n\n  function isAllowedValue<T, A>(allowed: T, value: string): A | false {\n    if (typeof value !== 'string') {\n      return false;\n    }\n    // necessary for assuring the generic conforms to the Array interface\n    if (!Array.isArray(allowed)) {\n      return false;\n    }\n    // reset the type so that the next narrowing works well\n    const lcValue = value.toLowerCase() as any;\n    // use the allow list to narrow the type to a specific subset of strings\n    if (~allowed.indexOf(lcValue)) {\n      return lcValue;\n    }\n\n    return false;\n  }\n\n  function findDirectionSetting(value: string) {\n    return isAllowedValue<typeof AllowedDirections, Direction>(\n      AllowedDirections,\n      value,\n    );\n  }\n\n  function findAlignSetting(value: string) {\n    return isAllowedValue<typeof AllowedAlignments, Alignment>(\n      AllowedAlignments,\n      value,\n    );\n  }\n\n  function extend(obj: Record<string, any>, ...rest: Record<string, any>[]) {\n    let i = 1;\n    for (; i < arguments.length; i++) {\n      const cobj = arguments[i];\n      for (const p in cobj) {\n        obj[p] = cobj[p];\n      }\n    }\n\n    return obj;\n  }\n\n  function VTTCue(startTime: number, endTime: number, text: string) {\n    const cue = this as VTTCuePolyfill;\n    const baseObj = { enumerable: true };\n    /**\n     * Shim implementation specific properties. These properties are not in\n     * the spec.\n     */\n\n    // Lets us know when the VTTCue's data has changed in such a way that we need\n    // to recompute its display state. This lets us compute its display state\n    // lazily.\n    cue.hasBeenReset = false;\n\n    /**\n     * VTTCue and TextTrackCue properties\n     * http://dev.w3.org/html5/webvtt/#vttcue-interface\n     */\n\n    let _id = '';\n    let _pauseOnExit = false;\n    let _startTime = startTime;\n    let _endTime = endTime;\n    let _text = text;\n    let _region = null;\n    let _vertical: Direction = '';\n    let _snapToLines = true;\n    let _line: number | 'auto' = 'auto';\n    let _lineAlign: Alignment = 'start';\n    let _position = 50;\n    let _positionAlign: Alignment = 'middle';\n    let _size = 50;\n    let _align: Alignment = 'middle';\n\n    Object.defineProperty(\n      cue,\n      'id',\n      extend({}, baseObj, {\n        get: function () {\n          return _id;\n        },\n        set: function (value: string) {\n          _id = '' + value;\n        },\n      }),\n    );\n\n    Object.defineProperty(\n      cue,\n      'pauseOnExit',\n      extend({}, baseObj, {\n        get: function () {\n          return _pauseOnExit;\n        },\n        set: function (value: boolean) {\n          _pauseOnExit = !!value;\n        },\n      }),\n    );\n\n    Object.defineProperty(\n      cue,\n      'startTime',\n      extend({}, baseObj, {\n        get: function () {\n          return _startTime;\n        },\n        set: function (value: number) {\n          if (typeof value !== 'number') {\n            throw new TypeError('Start time must be set to a number.');\n          }\n\n          _startTime = value;\n          this.hasBeenReset = true;\n        },\n      }),\n    );\n\n    Object.defineProperty(\n      cue,\n      'endTime',\n      extend({}, baseObj, {\n        get: function () {\n          return _endTime;\n        },\n        set: function (value: number) {\n          if (typeof value !== 'number') {\n            throw new TypeError('End time must be set to a number.');\n          }\n\n          _endTime = value;\n          this.hasBeenReset = true;\n        },\n      }),\n    );\n\n    Object.defineProperty(\n      cue,\n      'text',\n      extend({}, baseObj, {\n        get: function () {\n          return _text;\n        },\n        set: function (value: string) {\n          _text = '' + value;\n          this.hasBeenReset = true;\n        },\n      }),\n    );\n\n    // todo: implement VTTRegion polyfill?\n    Object.defineProperty(\n      cue,\n      'region',\n      extend({}, baseObj, {\n        get: function () {\n          return _region;\n        },\n        set: function (value: any) {\n          _region = value;\n          this.hasBeenReset = true;\n        },\n      }),\n    );\n\n    Object.defineProperty(\n      cue,\n      'vertical',\n      extend({}, baseObj, {\n        get: function () {\n          return _vertical;\n        },\n        set: function (value: string) {\n          const setting = findDirectionSetting(value);\n          // Have to check for false because the setting an be an empty string.\n          if (setting === false) {\n            throw new SyntaxError(\n              'An invalid or illegal string was specified.',\n            );\n          }\n\n          _vertical = setting;\n          this.hasBeenReset = true;\n        },\n      }),\n    );\n\n    Object.defineProperty(\n      cue,\n      'snapToLines',\n      extend({}, baseObj, {\n        get: function () {\n          return _snapToLines;\n        },\n        set: function (value: boolean) {\n          _snapToLines = !!value;\n          this.hasBeenReset = true;\n        },\n      }),\n    );\n\n    Object.defineProperty(\n      cue,\n      'line',\n      extend({}, baseObj, {\n        get: function () {\n          return _line;\n        },\n        set: function (value: number | 'auto') {\n          if (typeof value !== 'number' && value !== 'auto') {\n            throw new SyntaxError(\n              'An invalid number or illegal string was specified.',\n            );\n          }\n\n          _line = value;\n          this.hasBeenReset = true;\n        },\n      }),\n    );\n\n    Object.defineProperty(\n      cue,\n      'lineAlign',\n      extend({}, baseObj, {\n        get: function () {\n          return _lineAlign;\n        },\n        set: function (value: string) {\n          const setting = findAlignSetting(value);\n          if (!setting) {\n            throw new SyntaxError(\n              'An invalid or illegal string was specified.',\n            );\n          }\n\n          _lineAlign = setting;\n          this.hasBeenReset = true;\n        },\n      }),\n    );\n\n    Object.defineProperty(\n      cue,\n      'position',\n      extend({}, baseObj, {\n        get: function () {\n          return _position;\n        },\n        set: function (value: number) {\n          if (value < 0 || value > 100) {\n            throw new Error('Position must be between 0 and 100.');\n          }\n\n          _position = value;\n          this.hasBeenReset = true;\n        },\n      }),\n    );\n\n    Object.defineProperty(\n      cue,\n      'positionAlign',\n      extend({}, baseObj, {\n        get: function () {\n          return _positionAlign;\n        },\n        set: function (value: string) {\n          const setting = findAlignSetting(value);\n          if (!setting) {\n            throw new SyntaxError(\n              'An invalid or illegal string was specified.',\n            );\n          }\n\n          _positionAlign = setting;\n          this.hasBeenReset = true;\n        },\n      }),\n    );\n\n    Object.defineProperty(\n      cue,\n      'size',\n      extend({}, baseObj, {\n        get: function () {\n          return _size;\n        },\n        set: function (value: number) {\n          if (value < 0 || value > 100) {\n            throw new Error('Size must be between 0 and 100.');\n          }\n\n          _size = value;\n          this.hasBeenReset = true;\n        },\n      }),\n    );\n\n    Object.defineProperty(\n      cue,\n      'align',\n      extend({}, baseObj, {\n        get: function () {\n          return _align;\n        },\n        set: function (value: string) {\n          const setting = findAlignSetting(value);\n          if (!setting) {\n            throw new SyntaxError(\n              'An invalid or illegal string was specified.',\n            );\n          }\n\n          _align = setting;\n          this.hasBeenReset = true;\n        },\n      }),\n    );\n\n    /**\n     * Other <track> spec defined properties\n     */\n\n    // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#text-track-cue-display-state\n    cue.displayState = undefined;\n  }\n\n  /**\n   * VTTCue methods\n   */\n\n  VTTCue.prototype.getCueAsHTML = function () {\n    // Assume WebVTT.convertCueToDOMTree is on the global.\n    const WebVTT = (self as any).WebVTT;\n    return WebVTT.convertCueToDOMTree(self, this.text);\n  };\n  // this is a polyfill hack\n  return VTTCue as any as VTTCuePolyfill;\n})();\n", "/*\n * Source: https://github.com/mozilla/vtt.js/blob/master/dist/vtt.js\n */\n\nimport VTTCue from './vttcue';\n\nclass StringDecoder {\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  decode(data: string | any, options?: Object): string | never {\n    if (!data) {\n      return '';\n    }\n\n    if (typeof data !== 'string') {\n      throw new Error('Error - expected string data.');\n    }\n\n    return decodeURIComponent(encodeURIComponent(data));\n  }\n}\n\n// Try to parse input as a time stamp.\nexport function parseTimeStamp(input: string) {\n  function computeSeconds(h, m, s, f) {\n    return (h | 0) * 3600 + (m | 0) * 60 + (s | 0) + parseFloat(f || 0);\n  }\n\n  const m = input.match(/^(?:(\\d+):)?(\\d{2}):(\\d{2})(\\.\\d+)?/);\n  if (!m) {\n    return null;\n  }\n\n  if (parseFloat(m[2]) > 59) {\n    // Timestamp takes the form of [hours]:[minutes].[milliseconds]\n    // First position is hours as it's over 59.\n    return computeSeconds(m[2], m[3], 0, m[4]);\n  }\n  // Timestamp takes the form of [hours (optional)]:[minutes]:[seconds].[milliseconds]\n  return computeSeconds(m[1], m[2], m[3], m[4]);\n}\n\n// A settings object holds key/value pairs and will ignore anything but the first\n// assignment to a specific key.\nclass Settings {\n  private readonly values: { [key: string]: any } = Object.create(null);\n\n  // Only accept the first assignment to any key.\n  set(k: string, v: any) {\n    if (!this.get(k) && v !== '') {\n      this.values[k] = v;\n    }\n  }\n  // Return the value for a key, or a default value.\n  // If 'defaultKey' is passed then 'dflt' is assumed to be an object with\n  // a number of possible default values as properties where 'defaultKey' is\n  // the key of the property that will be chosen; otherwise it's assumed to be\n  // a single value.\n  get(k: string, dflt?: any, defaultKey?: string): any {\n    if (defaultKey) {\n      return this.has(k) ? this.values[k] : dflt[defaultKey];\n    }\n\n    return this.has(k) ? this.values[k] : dflt;\n  }\n  // Check whether we have a value for a key.\n  has(k: string): boolean {\n    return k in this.values;\n  }\n  // Accept a setting if its one of the given alternatives.\n  alt(k: string, v: any, a: any[]) {\n    for (let n = 0; n < a.length; ++n) {\n      if (v === a[n]) {\n        this.set(k, v);\n        break;\n      }\n    }\n  }\n  // Accept a setting if its a valid (signed) integer.\n  integer(k: string, v: any) {\n    if (/^-?\\d+$/.test(v)) {\n      // integer\n      this.set(k, parseInt(v, 10));\n    }\n  }\n  // Accept a setting if its a valid percentage.\n  percent(k: string, v: any): boolean {\n    if (/^([\\d]{1,3})(\\.[\\d]*)?%$/.test(v)) {\n      const percent = parseFloat(v);\n      if (percent >= 0 && percent <= 100) {\n        this.set(k, percent);\n        return true;\n      }\n    }\n    return false;\n  }\n}\n\n// Helper function to parse input into groups separated by 'groupDelim', and\n// interpret each group as a key/value pair separated by 'keyValueDelim'.\nfunction parseOptions(\n  input: string,\n  callback: (k: string, v: any) => void,\n  keyValueDelim: RegExp,\n  groupDelim?: RegExp,\n) {\n  const groups = groupDelim ? input.split(groupDelim) : [input];\n  for (const i in groups) {\n    if (typeof groups[i] !== 'string') {\n      continue;\n    }\n\n    const kv = groups[i].split(keyValueDelim);\n    if (kv.length !== 2) {\n      continue;\n    }\n\n    const k = kv[0];\n    const v = kv[1];\n    callback(k, v);\n  }\n}\n\nconst defaults = new VTTCue(0, 0, '');\n// 'middle' was changed to 'center' in the spec: https://github.com/w3c/webvtt/pull/244\n//  Safari doesn't yet support this change, but FF and Chrome do.\nconst center = (defaults.align as string) === 'middle' ? 'middle' : 'center';\n\nfunction parseCue(input: string, cue: VTTCue, regionList: Region[]) {\n  // Remember the original input if we need to throw an error.\n  const oInput = input;\n  // 4.1 WebVTT timestamp\n  function consumeTimeStamp(): number | never {\n    const ts = parseTimeStamp(input);\n    if (ts === null) {\n      throw new Error('Malformed timestamp: ' + oInput);\n    }\n\n    // Remove time stamp from input.\n    input = input.replace(/^[^\\sa-zA-Z-]+/, '');\n    return ts;\n  }\n\n  // 4.4.2 WebVTT cue settings\n  function consumeCueSettings(input: string, cue: VTTCue) {\n    const settings = new Settings();\n\n    parseOptions(\n      input,\n      function (k, v) {\n        let vals;\n        switch (k) {\n          case 'region':\n            // Find the last region we parsed with the same region id.\n            for (let i = regionList.length - 1; i >= 0; i--) {\n              if (regionList[i].id === v) {\n                settings.set(k, regionList[i].region);\n                break;\n              }\n            }\n            break;\n          case 'vertical':\n            settings.alt(k, v, ['rl', 'lr']);\n            break;\n          case 'line':\n            vals = v.split(',');\n            settings.integer(k, vals[0]);\n            if (settings.percent(k, vals[0])) {\n              settings.set('snapToLines', false);\n            }\n\n            settings.alt(k, vals[0], ['auto']);\n            if (vals.length === 2) {\n              settings.alt('lineAlign', vals[1], ['start', center, 'end']);\n            }\n\n            break;\n          case 'position':\n            vals = v.split(',');\n            settings.percent(k, vals[0]);\n            if (vals.length === 2) {\n              settings.alt('positionAlign', vals[1], [\n                'start',\n                center,\n                'end',\n                'line-left',\n                'line-right',\n                'auto',\n              ]);\n            }\n\n            break;\n          case 'size':\n            settings.percent(k, v);\n            break;\n          case 'align':\n            settings.alt(k, v, ['start', center, 'end', 'left', 'right']);\n            break;\n        }\n      },\n      /:/,\n      /\\s/,\n    );\n\n    // Apply default values for any missing fields.\n    cue.region = settings.get('region', null);\n    cue.vertical = settings.get('vertical', '');\n    let line = settings.get('line', 'auto');\n    if (line === 'auto' && defaults.line === -1) {\n      // set numeric line number for Safari\n      line = -1;\n    }\n    cue.line = line;\n    cue.lineAlign = settings.get('lineAlign', 'start');\n    cue.snapToLines = settings.get('snapToLines', true);\n    cue.size = settings.get('size', 100);\n    cue.align = settings.get('align', center);\n    let position = settings.get('position', 'auto');\n    if (position === 'auto' && defaults.position === 50) {\n      // set numeric position for Safari\n      position =\n        cue.align === 'start' || cue.align === 'left'\n          ? 0\n          : cue.align === 'end' || cue.align === 'right'\n            ? 100\n            : 50;\n    }\n    cue.position = position;\n  }\n\n  function skipWhitespace() {\n    input = input.replace(/^\\s+/, '');\n  }\n\n  // 4.1 WebVTT cue timings.\n  skipWhitespace();\n  cue.startTime = consumeTimeStamp(); // (1) collect cue start time\n  skipWhitespace();\n  if (input.slice(0, 3) !== '-->') {\n    // (3) next characters must match '-->'\n    throw new Error(\n      \"Malformed time stamp (time stamps must be separated by '-->'): \" +\n        oInput,\n    );\n  }\n  input = input.slice(3);\n  skipWhitespace();\n  cue.endTime = consumeTimeStamp(); // (5) collect cue end time\n\n  // 4.1 WebVTT cue settings list.\n  skipWhitespace();\n  consumeCueSettings(input, cue);\n}\n\nexport function fixLineBreaks(input: string): string {\n  return input.replace(/<br(?: \\/)?>/gi, '\\n');\n}\n\ntype Region = {\n  id: string;\n  region: any;\n};\n\nexport class VTTParser {\n  private state:\n    | 'INITIAL'\n    | 'HEADER'\n    | 'ID'\n    | 'CUE'\n    | 'CUETEXT'\n    | 'NOTE'\n    | 'BADWEBVTT'\n    | 'BADCUE' = 'INITIAL';\n  private buffer: string = '';\n  private decoder: StringDecoder = new StringDecoder();\n  private regionList: Region[] = [];\n  private cue: VTTCue | null = null;\n  public oncue?: (cue: VTTCue) => void;\n  public onparsingerror?: (error: Error) => void;\n  public onflush?: () => void;\n\n  parse(data?: string): VTTParser {\n    const _this = this;\n\n    // If there is no data then we won't decode it, but will just try to parse\n    // whatever is in buffer already. This may occur in circumstances, for\n    // example when flush() is called.\n    if (data) {\n      // Try to decode the data that we received.\n      _this.buffer += _this.decoder.decode(data, { stream: true });\n    }\n\n    function collectNextLine(): string {\n      let buffer: string = _this.buffer;\n      let pos = 0;\n\n      buffer = fixLineBreaks(buffer);\n\n      while (\n        pos < buffer.length &&\n        buffer[pos] !== '\\r' &&\n        buffer[pos] !== '\\n'\n      ) {\n        ++pos;\n      }\n\n      const line: string = buffer.slice(0, pos);\n      // Advance the buffer early in case we fail below.\n      if (buffer[pos] === '\\r') {\n        ++pos;\n      }\n\n      if (buffer[pos] === '\\n') {\n        ++pos;\n      }\n\n      _this.buffer = buffer.slice(pos);\n      return line;\n    }\n\n    // 3.2 WebVTT metadata header syntax\n    function parseHeader(input) {\n      parseOptions(\n        input,\n        function (k, v) {\n          // switch (k) {\n          // case 'region':\n          // 3.3 WebVTT region metadata header syntax\n          // console.log('parse region', v);\n          // parseRegion(v);\n          // break;\n          // }\n        },\n        /:/,\n      );\n    }\n\n    // 5.1 WebVTT file parsing.\n    try {\n      let line: string = '';\n      if (_this.state === 'INITIAL') {\n        // We can't start parsing until we have the first line.\n        if (!/\\r\\n|\\n/.test(_this.buffer)) {\n          return this;\n        }\n\n        line = collectNextLine();\n        // strip of UTF-8 BOM if any\n        // https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8\n        const m = line.match(/^(\u00EF\u00BB\u00BF)?WEBVTT([ \\t].*)?$/);\n        if (!m?.[0]) {\n          throw new Error('Malformed WebVTT signature.');\n        }\n\n        _this.state = 'HEADER';\n      }\n\n      let alreadyCollectedLine = false;\n      while (_this.buffer) {\n        // We can't parse a line until we have the full line.\n        if (!/\\r\\n|\\n/.test(_this.buffer)) {\n          return this;\n        }\n\n        if (!alreadyCollectedLine) {\n          line = collectNextLine();\n        } else {\n          alreadyCollectedLine = false;\n        }\n\n        switch (_this.state) {\n          case 'HEADER':\n            // 13-18 - Allow a header (metadata) under the WEBVTT line.\n            if (/:/.test(line)) {\n              parseHeader(line);\n            } else if (!line) {\n              // An empty line terminates the header and starts the body (cues).\n              _this.state = 'ID';\n            }\n            continue;\n          case 'NOTE':\n            // Ignore NOTE blocks.\n            if (!line) {\n              _this.state = 'ID';\n            }\n\n            continue;\n          case 'ID':\n            // Check for the start of NOTE blocks.\n            if (/^NOTE($|[ \\t])/.test(line)) {\n              _this.state = 'NOTE';\n              break;\n            }\n            // 19-29 - Allow any number of line terminators, then initialize new cue values.\n            if (!line) {\n              continue;\n            }\n\n            _this.cue = new VTTCue(0, 0, '');\n            _this.state = 'CUE';\n            // 30-39 - Check if self line contains an optional identifier or timing data.\n            if (line.indexOf('-->') === -1) {\n              _this.cue.id = line;\n              continue;\n            }\n          // Process line as start of a cue.\n          /* falls through */\n          case 'CUE':\n            // 40 - Collect cue timings and settings.\n            if (!_this.cue) {\n              _this.state = 'BADCUE';\n              continue;\n            }\n            try {\n              parseCue(line, _this.cue, _this.regionList);\n            } catch (e) {\n              // In case of an error ignore rest of the cue.\n              _this.cue = null;\n              _this.state = 'BADCUE';\n              continue;\n            }\n            _this.state = 'CUETEXT';\n            continue;\n          case 'CUETEXT':\n            {\n              const hasSubstring = line.indexOf('-->') !== -1;\n              // 34 - If we have an empty line then report the cue.\n              // 35 - If we have the special substring '-->' then report the cue,\n              // but do not collect the line as we need to process the current\n              // one as a new cue.\n              if (!line || (hasSubstring && (alreadyCollectedLine = true))) {\n                // We are done parsing self cue.\n                if (_this.oncue && _this.cue) {\n                  _this.oncue(_this.cue);\n                }\n\n                _this.cue = null;\n                _this.state = 'ID';\n                continue;\n              }\n              if (_this.cue === null) {\n                continue;\n              }\n\n              if (_this.cue.text) {\n                _this.cue.text += '\\n';\n              }\n              _this.cue.text += line;\n            }\n            continue;\n          case 'BADCUE':\n            // 54-62 - Collect and discard the remaining cue.\n            if (!line) {\n              _this.state = 'ID';\n            }\n        }\n      }\n    } catch (e) {\n      // If we are currently parsing a cue, report what we have.\n      if (_this.state === 'CUETEXT' && _this.cue && _this.oncue) {\n        _this.oncue(_this.cue);\n      }\n\n      _this.cue = null;\n      // Enter BADWEBVTT state if header was not parsed correctly otherwise\n      // another exception occurred so enter BADCUE state.\n      _this.state = _this.state === 'INITIAL' ? 'BADWEBVTT' : 'BADCUE';\n    }\n    return this;\n  }\n\n  flush(): VTTParser {\n    const _this = this;\n    try {\n      // Finish decoding the stream.\n      // _this.buffer += _this.decoder.decode();\n      // Synthesize the end of the current cue or region.\n      if (_this.cue || _this.state === 'HEADER') {\n        _this.buffer += '\\n\\n';\n        _this.parse();\n      }\n      // If we've flushed, parsed, and we're still on the INITIAL state then\n      // that means we don't have enough of the stream to parse the first\n      // line.\n      if (_this.state === 'INITIAL' || _this.state === 'BADWEBVTT') {\n        throw new Error('Malformed WebVTT signature.');\n      }\n    } catch (e) {\n      if (_this.onparsingerror) {\n        _this.onparsingerror(e);\n      }\n    }\n    if (_this.onflush) {\n      _this.onflush();\n    }\n\n    return this;\n  }\n}\n", "import { VTTParser } from './vttparser';\nimport { utf8ArrayToStr } from '../demux/id3';\nimport {\n  RationalTimestamp,\n  toMpegTsClockFromTimescale,\n} from './timescale-conversion';\nimport { normalizePts } from '../remux/mp4-remuxer';\nimport type { VTTCCs } from '../types/vtt';\n\nconst LINEBREAKS = /\\r\\n|\\n\\r|\\n|\\r/g;\n\n// String.prototype.startsWith is not supported in IE11\nconst startsWith = function (\n  inputString: string,\n  searchString: string,\n  position: number = 0,\n) {\n  return (\n    inputString.slice(position, position + searchString.length) === searchString\n  );\n};\n\nconst cueString2millis = function (timeString: string) {\n  let ts = parseInt(timeString.slice(-3));\n  const secs = parseInt(timeString.slice(-6, -4));\n  const mins = parseInt(timeString.slice(-9, -7));\n  const hours =\n    timeString.length > 9\n      ? parseInt(timeString.substring(0, timeString.indexOf(':')))\n      : 0;\n\n  if (\n    !Number.isFinite(ts) ||\n    !Number.isFinite(secs) ||\n    !Number.isFinite(mins) ||\n    !Number.isFinite(hours)\n  ) {\n    throw Error(`Malformed X-TIMESTAMP-MAP: Local:${timeString}`);\n  }\n\n  ts += 1000 * secs;\n  ts += 60 * 1000 * mins;\n  ts += 60 * 60 * 1000 * hours;\n\n  return ts;\n};\n\n// From https://github.com/darkskyapp/string-hash\nconst hash = function (text: string) {\n  let hash = 5381;\n  let i = text.length;\n  while (i) {\n    hash = (hash * 33) ^ text.charCodeAt(--i);\n  }\n\n  return (hash >>> 0).toString();\n};\n\n// Create a unique hash id for a cue based on start/end times and text.\n// This helps timeline-controller to avoid showing repeated captions.\nexport function generateCueId(\n  startTime: number,\n  endTime: number,\n  text: string,\n) {\n  return hash(startTime.toString()) + hash(endTime.toString()) + hash(text);\n}\n\nconst calculateOffset = function (vttCCs: VTTCCs, cc, presentationTime) {\n  let currCC = vttCCs[cc];\n  let prevCC = vttCCs[currCC.prevCC];\n\n  // This is the first discontinuity or cues have been processed since the last discontinuity\n  // Offset = current discontinuity time\n  if (!prevCC || (!prevCC.new && currCC.new)) {\n    vttCCs.ccOffset = vttCCs.presentationOffset = currCC.start;\n    currCC.new = false;\n    return;\n  }\n\n  // There have been discontinuities since cues were last parsed.\n  // Offset = time elapsed\n  while (prevCC?.new) {\n    vttCCs.ccOffset += currCC.start - prevCC.start;\n    currCC.new = false;\n    currCC = prevCC;\n    prevCC = vttCCs[currCC.prevCC];\n  }\n\n  vttCCs.presentationOffset = presentationTime;\n};\n\nexport function parseWebVTT(\n  vttByteArray: ArrayBuffer,\n  initPTS: RationalTimestamp | undefined,\n  vttCCs: VTTCCs,\n  cc: number,\n  timeOffset: number,\n  callBack: (cues: VTTCue[]) => void,\n  errorCallBack: (error: Error) => void,\n) {\n  const parser = new VTTParser();\n  // Convert byteArray into string, replacing any somewhat exotic linefeeds with \"\\n\", then split on that character.\n  // Uint8Array.prototype.reduce is not implemented in IE11\n  const vttLines = utf8ArrayToStr(new Uint8Array(vttByteArray))\n    .trim()\n    .replace(LINEBREAKS, '\\n')\n    .split('\\n');\n  const cues: VTTCue[] = [];\n  const init90kHz = initPTS\n    ? toMpegTsClockFromTimescale(initPTS.baseTime, initPTS.timescale)\n    : 0;\n  let cueTime = '00:00.000';\n  let timestampMapMPEGTS = 0;\n  let timestampMapLOCAL = 0;\n  let parsingError: Error;\n  let inHeader = true;\n\n  parser.oncue = function (cue: VTTCue) {\n    // Adjust cue timing; clamp cues to start no earlier than - and drop cues that don't end after - 0 on timeline.\n    const currCC = vttCCs[cc];\n    let cueOffset = vttCCs.ccOffset;\n\n    // Calculate subtitle PTS offset\n    const webVttMpegTsMapOffset = (timestampMapMPEGTS - init90kHz) / 90000;\n\n    // Update offsets for new discontinuities\n    if (currCC?.new) {\n      if (timestampMapLOCAL !== undefined) {\n        // When local time is provided, offset = discontinuity start time - local time\n        cueOffset = vttCCs.ccOffset = currCC.start;\n      } else {\n        calculateOffset(vttCCs, cc, webVttMpegTsMapOffset);\n      }\n    }\n    if (webVttMpegTsMapOffset) {\n      if (!initPTS) {\n        parsingError = new Error('Missing initPTS for VTT MPEGTS');\n        return;\n      }\n      // If we have MPEGTS, offset = presentation time + discontinuity offset\n      cueOffset = webVttMpegTsMapOffset - vttCCs.presentationOffset;\n    }\n\n    const duration = cue.endTime - cue.startTime;\n    const startTime =\n      normalizePts(\n        (cue.startTime + cueOffset - timestampMapLOCAL) * 90000,\n        timeOffset * 90000,\n      ) / 90000;\n    cue.startTime = Math.max(startTime, 0);\n    cue.endTime = Math.max(startTime + duration, 0);\n\n    //trim trailing webvtt block whitespaces\n    const text = cue.text.trim();\n\n    // Fix encoding of special characters\n    cue.text = decodeURIComponent(encodeURIComponent(text));\n\n    // If the cue was not assigned an id from the VTT file (line above the content), create one.\n    if (!cue.id) {\n      cue.id = generateCueId(cue.startTime, cue.endTime, text);\n    }\n\n    if (cue.endTime > 0) {\n      cues.push(cue);\n    }\n  };\n\n  parser.onparsingerror = function (error: Error) {\n    parsingError = error;\n  };\n\n  parser.onflush = function () {\n    if (parsingError) {\n      errorCallBack(parsingError);\n      return;\n    }\n    callBack(cues);\n  };\n\n  // Go through contents line by line.\n  vttLines.forEach((line) => {\n    if (inHeader) {\n      // Look for X-TIMESTAMP-MAP in header.\n      if (startsWith(line, 'X-TIMESTAMP-MAP=')) {\n        // Once found, no more are allowed anyway, so stop searching.\n        inHeader = false;\n        // Extract LOCAL and MPEGTS.\n        line\n          .slice(16)\n          .split(',')\n          .forEach((timestamp) => {\n            if (startsWith(timestamp, 'LOCAL:')) {\n              cueTime = timestamp.slice(6);\n            } else if (startsWith(timestamp, 'MPEGTS:')) {\n              timestampMapMPEGTS = parseInt(timestamp.slice(7));\n            }\n          });\n        try {\n          // Convert cue time to seconds\n          timestampMapLOCAL = cueString2millis(cueTime) / 1000;\n        } catch (error) {\n          parsingError = error;\n        }\n        // Return without parsing X-TIMESTAMP-MAP line.\n        return;\n      } else if (line === '') {\n        inHeader = false;\n      }\n    }\n    // Parse line by default.\n    parser.parse(line + '\\n');\n  });\n\n  parser.flush();\n}\n", "import { findBox } from './mp4-tools';\nimport { parseTimeStamp } from './vttparser';\nimport VTTCue from './vttcue';\nimport { utf8ArrayToStr } from '../demux/id3';\nimport {\n  RationalTimestamp,\n  toTimescaleFromScale,\n} from './timescale-conversion';\nimport { generateCueId } from './webvtt-parser';\n\nexport const IMSC1_CODEC = 'stpp.ttml.im1t';\n\n// Time format: h:m:s:frames(.subframes)\nconst HMSF_REGEX = /^(\\d{2,}):(\\d{2}):(\\d{2}):(\\d{2})\\.?(\\d+)?$/;\n\n// Time format: hours, minutes, seconds, milliseconds, frames, ticks\nconst TIME_UNIT_REGEX = /^(\\d*(?:\\.\\d*)?)(h|m|s|ms|f|t)$/;\n\nconst textAlignToLineAlign: Partial<Record<string, LineAlignSetting>> = {\n  left: 'start',\n  center: 'center',\n  right: 'end',\n  start: 'start',\n  end: 'end',\n};\n\nexport function parseIMSC1(\n  payload: ArrayBuffer,\n  initPTS: RationalTimestamp,\n  callBack: (cues: Array<VTTCue>) => any,\n  errorCallBack: (error: Error) => any,\n) {\n  const results = findBox(new Uint8Array(payload), ['mdat']);\n  if (results.length === 0) {\n    errorCallBack(new Error('Could not parse IMSC1 mdat'));\n    return;\n  }\n\n  const ttmlList = results.map((mdat) => utf8ArrayToStr(mdat));\n\n  const syncTime = toTimescaleFromScale(initPTS.baseTime, 1, initPTS.timescale);\n\n  try {\n    ttmlList.forEach((ttml) => callBack(parseTTML(ttml, syncTime)));\n  } catch (error) {\n    errorCallBack(error);\n  }\n}\n\nfunction parseTTML(ttml: string, syncTime: number): Array<VTTCue> {\n  const parser = new DOMParser();\n  const xmlDoc = parser.parseFromString(ttml, 'text/xml');\n  const tt = xmlDoc.getElementsByTagName('tt')[0];\n  if (!tt) {\n    throw new Error('Invalid ttml');\n  }\n  const defaultRateInfo = {\n    frameRate: 30,\n    subFrameRate: 1,\n    frameRateMultiplier: 0,\n    tickRate: 0,\n  };\n  const rateInfo: Object = Object.keys(defaultRateInfo).reduce(\n    (result, key) => {\n      result[key] = tt.getAttribute(`ttp:${key}`) || defaultRateInfo[key];\n      return result;\n    },\n    {},\n  );\n\n  const trim = tt.getAttribute('xml:space') !== 'preserve';\n\n  const styleElements = collectionToDictionary(\n    getElementCollection(tt, 'styling', 'style'),\n  );\n  const regionElements = collectionToDictionary(\n    getElementCollection(tt, 'layout', 'region'),\n  );\n  const cueElements = getElementCollection(tt, 'body', '[begin]');\n\n  return [].map\n    .call(cueElements, (cueElement) => {\n      const cueText = getTextContent(cueElement, trim);\n\n      if (!cueText || !cueElement.hasAttribute('begin')) {\n        return null;\n      }\n      const startTime = parseTtmlTime(\n        cueElement.getAttribute('begin'),\n        rateInfo,\n      );\n      const duration = parseTtmlTime(cueElement.getAttribute('dur'), rateInfo);\n      let endTime = parseTtmlTime(cueElement.getAttribute('end'), rateInfo);\n      if (startTime === null) {\n        throw timestampParsingError(cueElement);\n      }\n      if (endTime === null) {\n        if (duration === null) {\n          throw timestampParsingError(cueElement);\n        }\n        endTime = startTime + duration;\n      }\n      const cue = new VTTCue(startTime - syncTime, endTime - syncTime, cueText);\n      cue.id = generateCueId(cue.startTime, cue.endTime, cue.text);\n\n      const region = regionElements[cueElement.getAttribute('region')];\n      const style = styleElements[cueElement.getAttribute('style')];\n\n      // Apply styles to cue\n      const styles = getTtmlStyles(region, style, styleElements);\n      const { textAlign } = styles;\n      if (textAlign) {\n        // cue.positionAlign not settable in FF~2016\n        const lineAlign = textAlignToLineAlign[textAlign];\n        if (lineAlign) {\n          cue.lineAlign = lineAlign;\n        }\n        cue.align = textAlign as AlignSetting;\n      }\n      Object.assign(cue, styles);\n\n      return cue;\n    })\n    .filter((cue) => cue !== null);\n}\n\nfunction getElementCollection(\n  fromElement,\n  parentName,\n  childName,\n): Array<HTMLElement> {\n  const parent = fromElement.getElementsByTagName(parentName)[0];\n  if (parent) {\n    return [].slice.call(parent.querySelectorAll(childName));\n  }\n  return [];\n}\n\nfunction collectionToDictionary(elementsWithId: Array<HTMLElement>): {\n  [id: string]: HTMLElement;\n} {\n  return elementsWithId.reduce((dict, element: HTMLElement) => {\n    const id = element.getAttribute('xml:id');\n    if (id) {\n      dict[id] = element;\n    }\n    return dict;\n  }, {});\n}\n\nfunction getTextContent(element, trim): string {\n  return [].slice.call(element.childNodes).reduce((str, node, i) => {\n    if (node.nodeName === 'br' && i) {\n      return str + '\\n';\n    }\n    if (node.childNodes?.length) {\n      return getTextContent(node, trim);\n    } else if (trim) {\n      return str + node.textContent.trim().replace(/\\s+/g, ' ');\n    }\n    return str + node.textContent;\n  }, '');\n}\n\nfunction getTtmlStyles(\n  region,\n  style,\n  styleElements,\n): { [style: string]: string } {\n  const ttsNs = 'http://www.w3.org/ns/ttml#styling';\n  let regionStyle = null;\n  const styleAttributes = [\n    'displayAlign',\n    'textAlign',\n    'color',\n    'backgroundColor',\n    'fontSize',\n    'fontFamily',\n    // 'fontWeight',\n    // 'lineHeight',\n    // 'wrapOption',\n    // 'fontStyle',\n    // 'direction',\n    // 'writingMode'\n  ];\n\n  const regionStyleName = region?.hasAttribute('style')\n    ? region.getAttribute('style')\n    : null;\n\n  if (regionStyleName && styleElements.hasOwnProperty(regionStyleName)) {\n    regionStyle = styleElements[regionStyleName];\n  }\n\n  return styleAttributes.reduce((styles, name) => {\n    const value =\n      getAttributeNS(style, ttsNs, name) ||\n      getAttributeNS(region, ttsNs, name) ||\n      getAttributeNS(regionStyle, ttsNs, name);\n    if (value) {\n      styles[name] = value;\n    }\n    return styles;\n  }, {});\n}\n\nfunction getAttributeNS(element, ns, name): string | null {\n  if (!element) {\n    return null;\n  }\n  return element.hasAttributeNS(ns, name)\n    ? element.getAttributeNS(ns, name)\n    : null;\n}\n\nfunction timestampParsingError(node) {\n  return new Error(`Could not parse ttml timestamp ${node}`);\n}\n\nfunction parseTtmlTime(timeAttributeValue, rateInfo): number | null {\n  if (!timeAttributeValue) {\n    return null;\n  }\n  let seconds: number | null = parseTimeStamp(timeAttributeValue);\n  if (seconds === null) {\n    if (HMSF_REGEX.test(timeAttributeValue)) {\n      seconds = parseHoursMinutesSecondsFrames(timeAttributeValue, rateInfo);\n    } else if (TIME_UNIT_REGEX.test(timeAttributeValue)) {\n      seconds = parseTimeUnits(timeAttributeValue, rateInfo);\n    }\n  }\n  return seconds;\n}\n\nfunction parseHoursMinutesSecondsFrames(timeAttributeValue, rateInfo): number {\n  const m = HMSF_REGEX.exec(timeAttributeValue) as Array<any>;\n  const frames = (m[4] | 0) + (m[5] | 0) / rateInfo.subFrameRate;\n  return (\n    (m[1] | 0) * 3600 +\n    (m[2] | 0) * 60 +\n    (m[3] | 0) +\n    frames / rateInfo.frameRate\n  );\n}\n\nfunction parseTimeUnits(timeAttributeValue, rateInfo): number {\n  const m = TIME_UNIT_REGEX.exec(timeAttributeValue) as Array<any>;\n  const value = Number(m[1]);\n  const unit = m[2];\n  switch (unit) {\n    case 'h':\n      return value * 3600;\n    case 'm':\n      return value * 60;\n    case 'ms':\n      return value * 1000;\n    case 'f':\n      return value / rateInfo.frameRate;\n    case 't':\n      return value / rateInfo.tickRate;\n  }\n  return value;\n}\n", "import { Events } from '../events';\nimport Cea608Parser, { CaptionScreen } from '../utils/cea-608-parser';\nimport OutputFilter from '../utils/output-filter';\nimport { parseWebVTT } from '../utils/webvtt-parser';\nimport {\n  sendAddTrackEvent,\n  clearCurrentCues,\n  addCueToTrack,\n  removeCuesInRange,\n  filterSubtitleTracks,\n} from '../utils/texttrack-utils';\nimport {\n  subtitleOptionsIdentical,\n  subtitleTrackMatchesTextTrack,\n} from '../utils/media-option-attributes';\nimport { parseIMSC1, IMSC1_CODEC } from '../utils/imsc1-ttml-parser';\nimport { appendUint8Array } from '../utils/mp4-tools';\nimport { PlaylistLevelType } from '../types/loader';\nimport { Fragment } from '../loader/fragment';\nimport type {\n  FragParsingUserdataData,\n  FragLoadedData,\n  FragDecryptedData,\n  MediaAttachingData,\n  ManifestLoadedData,\n  InitPTSFoundData,\n  SubtitleTracksUpdatedData,\n  BufferFlushingData,\n  FragLoadingData,\n} from '../types/events';\nimport { logger } from '../utils/logger';\nimport type Hls from '../hls';\nimport type { ComponentAPI } from '../types/component-api';\nimport type { HlsConfig } from '../config';\nimport type { CuesInterface } from '../utils/cues';\nimport type { MediaPlaylist } from '../types/media-playlist';\nimport type { VTTCCs } from '../types/vtt';\nimport type { RationalTimestamp } from '../utils/timescale-conversion';\n\ntype TrackProperties = {\n  label: string;\n  languageCode: string;\n  media?: MediaPlaylist;\n};\n\ntype NonNativeCaptionsTrack = {\n  _id?: string;\n  label: string;\n  kind: string;\n  default: boolean;\n  closedCaptions?: MediaPlaylist;\n  subtitleTrack?: MediaPlaylist;\n};\n\nexport class TimelineController implements ComponentAPI {\n  private hls: Hls;\n  private media: HTMLMediaElement | null = null;\n  private config: HlsConfig;\n  private enabled: boolean = true;\n  private Cues: CuesInterface;\n  private textTracks: Array<TextTrack> = [];\n  private tracks: Array<MediaPlaylist> = [];\n  private initPTS: RationalTimestamp[] = [];\n  private unparsedVttFrags: Array<FragLoadedData | FragDecryptedData> = [];\n  private captionsTracks: Record<string, TextTrack> = {};\n  private nonNativeCaptionsTracks: Record<string, NonNativeCaptionsTrack> = {};\n  private cea608Parser1?: Cea608Parser;\n  private cea608Parser2?: Cea608Parser;\n  private lastCc: number = -1; // Last video (CEA-608) fragment CC\n  private lastSn: number = -1; // Last video (CEA-608) fragment MSN\n  private lastPartIndex: number = -1; // Last video (CEA-608) fragment Part Index\n  private prevCC: number = -1; // Last subtitle fragment CC\n  private vttCCs: VTTCCs = newVTTCCs();\n  private captionsProperties: {\n    textTrack1: TrackProperties;\n    textTrack2: TrackProperties;\n    textTrack3: TrackProperties;\n    textTrack4: TrackProperties;\n  };\n\n  constructor(hls: Hls) {\n    this.hls = hls;\n    this.config = hls.config;\n    this.Cues = hls.config.cueHandler;\n\n    this.captionsProperties = {\n      textTrack1: {\n        label: this.config.captionsTextTrack1Label,\n        languageCode: this.config.captionsTextTrack1LanguageCode,\n      },\n      textTrack2: {\n        label: this.config.captionsTextTrack2Label,\n        languageCode: this.config.captionsTextTrack2LanguageCode,\n      },\n      textTrack3: {\n        label: this.config.captionsTextTrack3Label,\n        languageCode: this.config.captionsTextTrack3LanguageCode,\n      },\n      textTrack4: {\n        label: this.config.captionsTextTrack4Label,\n        languageCode: this.config.captionsTextTrack4LanguageCode,\n      },\n    };\n\n    hls.on(Events.MEDIA_ATTACHING, this.onMediaAttaching, this);\n    hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n    hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    hls.on(Events.MANIFEST_LOADED, this.onManifestLoaded, this);\n    hls.on(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);\n    hls.on(Events.FRAG_LOADING, this.onFragLoading, this);\n    hls.on(Events.FRAG_LOADED, this.onFragLoaded, this);\n    hls.on(Events.FRAG_PARSING_USERDATA, this.onFragParsingUserdata, this);\n    hls.on(Events.FRAG_DECRYPTED, this.onFragDecrypted, this);\n    hls.on(Events.INIT_PTS_FOUND, this.onInitPtsFound, this);\n    hls.on(Events.SUBTITLE_TRACKS_CLEARED, this.onSubtitleTracksCleared, this);\n    hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);\n  }\n\n  public destroy(): void {\n    const { hls } = this;\n    hls.off(Events.MEDIA_ATTACHING, this.onMediaAttaching, this);\n    hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n    hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    hls.off(Events.MANIFEST_LOADED, this.onManifestLoaded, this);\n    hls.off(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);\n    hls.off(Events.FRAG_LOADING, this.onFragLoading, this);\n    hls.off(Events.FRAG_LOADED, this.onFragLoaded, this);\n    hls.off(Events.FRAG_PARSING_USERDATA, this.onFragParsingUserdata, this);\n    hls.off(Events.FRAG_DECRYPTED, this.onFragDecrypted, this);\n    hls.off(Events.INIT_PTS_FOUND, this.onInitPtsFound, this);\n    hls.off(Events.SUBTITLE_TRACKS_CLEARED, this.onSubtitleTracksCleared, this);\n    hls.off(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);\n    // @ts-ignore\n    this.hls = this.config = null;\n    this.cea608Parser1 = this.cea608Parser2 = undefined;\n  }\n\n  private initCea608Parsers() {\n    if (\n      this.config.enableCEA708Captions &&\n      (!this.cea608Parser1 || !this.cea608Parser2)\n    ) {\n      const channel1 = new OutputFilter(this, 'textTrack1');\n      const channel2 = new OutputFilter(this, 'textTrack2');\n      const channel3 = new OutputFilter(this, 'textTrack3');\n      const channel4 = new OutputFilter(this, 'textTrack4');\n      this.cea608Parser1 = new Cea608Parser(1, channel1, channel2);\n      this.cea608Parser2 = new Cea608Parser(3, channel3, channel4);\n    }\n  }\n\n  public addCues(\n    trackName: string,\n    startTime: number,\n    endTime: number,\n    screen: CaptionScreen,\n    cueRanges: Array<[number, number]>,\n  ) {\n    // skip cues which overlap more than 50% with previously parsed time ranges\n    let merged = false;\n    for (let i = cueRanges.length; i--; ) {\n      const cueRange = cueRanges[i];\n      const overlap = intersection(\n        cueRange[0],\n        cueRange[1],\n        startTime,\n        endTime,\n      );\n      if (overlap >= 0) {\n        cueRange[0] = Math.min(cueRange[0], startTime);\n        cueRange[1] = Math.max(cueRange[1], endTime);\n        merged = true;\n        if (overlap / (endTime - startTime) > 0.5) {\n          return;\n        }\n      }\n    }\n    if (!merged) {\n      cueRanges.push([startTime, endTime]);\n    }\n\n    if (this.config.renderTextTracksNatively) {\n      const track = this.captionsTracks[trackName];\n      this.Cues.newCue(track, startTime, endTime, screen);\n    } else {\n      const cues = this.Cues.newCue(null, startTime, endTime, screen);\n      this.hls.trigger(Events.CUES_PARSED, {\n        type: 'captions',\n        cues,\n        track: trackName,\n      });\n    }\n  }\n\n  // Triggered when an initial PTS is found; used for synchronisation of WebVTT.\n  private onInitPtsFound(\n    event: Events.INIT_PTS_FOUND,\n    { frag, id, initPTS, timescale }: InitPTSFoundData,\n  ) {\n    const { unparsedVttFrags } = this;\n    if (id === 'main') {\n      this.initPTS[frag.cc] = { baseTime: initPTS, timescale };\n    }\n\n    // Due to asynchronous processing, initial PTS may arrive later than the first VTT fragments are loaded.\n    // Parse any unparsed fragments upon receiving the initial PTS.\n    if (unparsedVttFrags.length) {\n      this.unparsedVttFrags = [];\n      unparsedVttFrags.forEach((frag) => {\n        this.onFragLoaded(Events.FRAG_LOADED, frag as FragLoadedData);\n      });\n    }\n  }\n\n  private getExistingTrack(label: string, language: string): TextTrack | null {\n    const { media } = this;\n    if (media) {\n      for (let i = 0; i < media.textTracks.length; i++) {\n        const textTrack = media.textTracks[i];\n        if (\n          canReuseVttTextTrack(textTrack, {\n            name: label,\n            lang: language,\n            attrs: {} as any,\n          })\n        ) {\n          return textTrack;\n        }\n      }\n    }\n    return null;\n  }\n\n  public createCaptionsTrack(trackName: string) {\n    if (this.config.renderTextTracksNatively) {\n      this.createNativeTrack(trackName);\n    } else {\n      this.createNonNativeTrack(trackName);\n    }\n  }\n\n  private createNativeTrack(trackName: string) {\n    if (this.captionsTracks[trackName]) {\n      return;\n    }\n    const { captionsProperties, captionsTracks, media } = this;\n    const { label, languageCode } = captionsProperties[trackName];\n    // Enable reuse of existing text track.\n    const existingTrack = this.getExistingTrack(label, languageCode);\n    if (!existingTrack) {\n      const textTrack = this.createTextTrack('captions', label, languageCode);\n      if (textTrack) {\n        // Set a special property on the track so we know it's managed by Hls.js\n        textTrack[trackName] = true;\n        captionsTracks[trackName] = textTrack;\n      }\n    } else {\n      captionsTracks[trackName] = existingTrack;\n      clearCurrentCues(captionsTracks[trackName]);\n      sendAddTrackEvent(captionsTracks[trackName], media as HTMLMediaElement);\n    }\n  }\n\n  private createNonNativeTrack(trackName: string) {\n    if (this.nonNativeCaptionsTracks[trackName]) {\n      return;\n    }\n    // Create a list of a single track for the provider to consume\n    const trackProperties: TrackProperties = this.captionsProperties[trackName];\n    if (!trackProperties) {\n      return;\n    }\n    const label = trackProperties.label as string;\n    const track = {\n      _id: trackName,\n      label,\n      kind: 'captions',\n      default: trackProperties.media ? !!trackProperties.media.default : false,\n      closedCaptions: trackProperties.media,\n    };\n    this.nonNativeCaptionsTracks[trackName] = track;\n    this.hls.trigger(Events.NON_NATIVE_TEXT_TRACKS_FOUND, { tracks: [track] });\n  }\n\n  private createTextTrack(\n    kind: TextTrackKind,\n    label: string,\n    lang?: string,\n  ): TextTrack | undefined {\n    const media = this.media;\n    if (!media) {\n      return;\n    }\n    return media.addTextTrack(kind, label, lang);\n  }\n\n  private onMediaAttaching(\n    event: Events.MEDIA_ATTACHING,\n    data: MediaAttachingData,\n  ) {\n    this.media = data.media;\n    this._cleanTracks();\n  }\n\n  private onMediaDetaching() {\n    const { captionsTracks } = this;\n    Object.keys(captionsTracks).forEach((trackName) => {\n      clearCurrentCues(captionsTracks[trackName]);\n      delete captionsTracks[trackName];\n    });\n    this.nonNativeCaptionsTracks = {};\n  }\n\n  private onManifestLoading() {\n    // Detect discontinuity in video fragment (CEA-608) parsing\n    this.lastCc = -1;\n    this.lastSn = -1;\n    this.lastPartIndex = -1;\n    // Detect discontinuity in subtitle manifests\n    this.prevCC = -1;\n    this.vttCCs = newVTTCCs();\n    // Reset tracks\n    this._cleanTracks();\n    this.tracks = [];\n    this.captionsTracks = {};\n    this.nonNativeCaptionsTracks = {};\n    this.textTracks = [];\n    this.unparsedVttFrags = [];\n    this.initPTS = [];\n    if (this.cea608Parser1 && this.cea608Parser2) {\n      this.cea608Parser1.reset();\n      this.cea608Parser2.reset();\n    }\n  }\n\n  private _cleanTracks() {\n    // clear outdated subtitles\n    const { media } = this;\n    if (!media) {\n      return;\n    }\n    const textTracks = media.textTracks;\n    if (textTracks) {\n      for (let i = 0; i < textTracks.length; i++) {\n        clearCurrentCues(textTracks[i]);\n      }\n    }\n  }\n\n  private onSubtitleTracksUpdated(\n    event: Events.SUBTITLE_TRACKS_UPDATED,\n    data: SubtitleTracksUpdatedData,\n  ) {\n    const tracks: Array<MediaPlaylist> = data.subtitleTracks || [];\n    const hasIMSC1 = tracks.some((track) => track.textCodec === IMSC1_CODEC);\n    if (this.config.enableWebVTT || (hasIMSC1 && this.config.enableIMSC1)) {\n      const listIsIdentical = subtitleOptionsIdentical(this.tracks, tracks);\n      if (listIsIdentical) {\n        this.tracks = tracks;\n        return;\n      }\n      this.textTracks = [];\n      this.tracks = tracks;\n\n      if (this.config.renderTextTracksNatively) {\n        const media = this.media;\n        const inUseTracks: (TextTrack | null)[] | null = media\n          ? filterSubtitleTracks(media.textTracks)\n          : null;\n\n        this.tracks.forEach((track, index) => {\n          // Reuse tracks with the same label and lang, but do not reuse 608/708 tracks\n          let textTrack: TextTrack | undefined;\n          if (inUseTracks) {\n            let inUseTrack: TextTrack | null = null;\n            for (let i = 0; i < inUseTracks.length; i++) {\n              if (\n                inUseTracks[i] &&\n                canReuseVttTextTrack(inUseTracks[i], track)\n              ) {\n                inUseTrack = inUseTracks[i];\n                inUseTracks[i] = null;\n                break;\n              }\n            }\n            if (inUseTrack) {\n              textTrack = inUseTrack;\n            }\n          }\n          if (textTrack) {\n            clearCurrentCues(textTrack);\n          } else {\n            const textTrackKind = captionsOrSubtitlesFromCharacteristics(track);\n            textTrack = this.createTextTrack(\n              textTrackKind,\n              track.name,\n              track.lang,\n            );\n            if (textTrack) {\n              textTrack.mode = 'disabled';\n            }\n          }\n          if (textTrack) {\n            this.textTracks.push(textTrack);\n          }\n        });\n        // Warn when video element has captions or subtitle TextTracks carried over from another source\n        if (inUseTracks?.length) {\n          const unusedTextTracks = inUseTracks\n            .filter((t) => t !== null)\n            .map((t) => (t as TextTrack).label);\n          if (unusedTextTracks.length) {\n            logger.warn(\n              `Media element contains unused subtitle tracks: ${unusedTextTracks.join(\n                ', ',\n              )}. Replace media element for each source to clear TextTracks and captions menu.`,\n            );\n          }\n        }\n      } else if (this.tracks.length) {\n        // Create a list of tracks for the provider to consume\n        const tracksList = this.tracks.map((track) => {\n          return {\n            label: track.name,\n            kind: track.type.toLowerCase(),\n            default: track.default,\n            subtitleTrack: track,\n          };\n        });\n        this.hls.trigger(Events.NON_NATIVE_TEXT_TRACKS_FOUND, {\n          tracks: tracksList,\n        });\n      }\n    }\n  }\n\n  private onManifestLoaded(\n    event: Events.MANIFEST_LOADED,\n    data: ManifestLoadedData,\n  ) {\n    if (this.config.enableCEA708Captions && data.captions) {\n      data.captions.forEach((captionsTrack) => {\n        const instreamIdMatch = /(?:CC|SERVICE)([1-4])/.exec(\n          captionsTrack.instreamId as string,\n        );\n        if (!instreamIdMatch) {\n          return;\n        }\n        const trackName = `textTrack${instreamIdMatch[1]}`;\n        const trackProperties: TrackProperties =\n          this.captionsProperties[trackName];\n        if (!trackProperties) {\n          return;\n        }\n        trackProperties.label = captionsTrack.name;\n        if (captionsTrack.lang) {\n          // optional attribute\n          trackProperties.languageCode = captionsTrack.lang;\n        }\n        trackProperties.media = captionsTrack;\n      });\n    }\n  }\n\n  private closedCaptionsForLevel(frag: Fragment): string | undefined {\n    const level = this.hls.levels[frag.level];\n    return level?.attrs['CLOSED-CAPTIONS'];\n  }\n\n  private onFragLoading(event: Events.FRAG_LOADING, data: FragLoadingData) {\n    // if this frag isn't contiguous, clear the parser so cues with bad start/end times aren't added to the textTrack\n    if (this.enabled && data.frag.type === PlaylistLevelType.MAIN) {\n      const { cea608Parser1, cea608Parser2, lastSn } = this;\n      const { cc, sn } = data.frag;\n      const partIndex = data.part?.index ?? -1;\n      if (cea608Parser1 && cea608Parser2) {\n        if (\n          sn !== lastSn + 1 ||\n          (sn === lastSn && partIndex !== this.lastPartIndex + 1) ||\n          cc !== this.lastCc\n        ) {\n          cea608Parser1.reset();\n          cea608Parser2.reset();\n        }\n      }\n      this.lastCc = cc as number;\n      this.lastSn = sn as number;\n      this.lastPartIndex = partIndex;\n    }\n  }\n\n  private onFragLoaded(\n    event: Events.FRAG_LOADED,\n    data: FragDecryptedData | FragLoadedData,\n  ) {\n    const { frag, payload } = data;\n    if (frag.type === PlaylistLevelType.SUBTITLE) {\n      // If fragment is subtitle type, parse as WebVTT.\n      if (payload.byteLength) {\n        const decryptData = frag.decryptdata;\n        // fragment after decryption has a stats object\n        const decrypted = 'stats' in data;\n        // If the subtitles are not encrypted, parse VTTs now. Otherwise, we need to wait.\n        if (decryptData == null || !decryptData.encrypted || decrypted) {\n          const trackPlaylistMedia = this.tracks[frag.level];\n          const vttCCs = this.vttCCs;\n          if (!vttCCs[frag.cc]) {\n            vttCCs[frag.cc] = {\n              start: frag.start,\n              prevCC: this.prevCC,\n              new: true,\n            };\n            this.prevCC = frag.cc;\n          }\n          if (\n            trackPlaylistMedia &&\n            trackPlaylistMedia.textCodec === IMSC1_CODEC\n          ) {\n            this._parseIMSC1(frag, payload);\n          } else {\n            this._parseVTTs(data);\n          }\n        }\n      } else {\n        // In case there is no payload, finish unsuccessfully.\n        this.hls.trigger(Events.SUBTITLE_FRAG_PROCESSED, {\n          success: false,\n          frag,\n          error: new Error('Empty subtitle payload'),\n        });\n      }\n    }\n  }\n\n  private _parseIMSC1(frag: Fragment, payload: ArrayBuffer) {\n    const hls = this.hls;\n    parseIMSC1(\n      payload,\n      this.initPTS[frag.cc],\n      (cues) => {\n        this._appendCues(cues, frag.level);\n        hls.trigger(Events.SUBTITLE_FRAG_PROCESSED, {\n          success: true,\n          frag: frag,\n        });\n      },\n      (error) => {\n        logger.log(`Failed to parse IMSC1: ${error}`);\n        hls.trigger(Events.SUBTITLE_FRAG_PROCESSED, {\n          success: false,\n          frag: frag,\n          error,\n        });\n      },\n    );\n  }\n\n  private _parseVTTs(data: FragDecryptedData | FragLoadedData) {\n    const { frag, payload } = data;\n    // We need an initial synchronisation PTS. Store fragments as long as none has arrived\n    const { initPTS, unparsedVttFrags } = this;\n    const maxAvCC = initPTS.length - 1;\n    if (!initPTS[frag.cc] && maxAvCC === -1) {\n      unparsedVttFrags.push(data);\n      return;\n    }\n\n    const hls = this.hls;\n    // Parse the WebVTT file contents.\n    const payloadWebVTT = frag.initSegment?.data\n      ? appendUint8Array(frag.initSegment.data, new Uint8Array(payload))\n      : payload;\n    parseWebVTT(\n      payloadWebVTT,\n      this.initPTS[frag.cc],\n      this.vttCCs,\n      frag.cc,\n      frag.start,\n      (cues) => {\n        this._appendCues(cues, frag.level);\n        hls.trigger(Events.SUBTITLE_FRAG_PROCESSED, {\n          success: true,\n          frag: frag,\n        });\n      },\n      (error) => {\n        const missingInitPTS =\n          error.message === 'Missing initPTS for VTT MPEGTS';\n        if (missingInitPTS) {\n          unparsedVttFrags.push(data);\n        } else {\n          this._fallbackToIMSC1(frag, payload);\n        }\n        // Something went wrong while parsing. Trigger event with success false.\n        logger.log(`Failed to parse VTT cue: ${error}`);\n        if (missingInitPTS && maxAvCC > frag.cc) {\n          return;\n        }\n        hls.trigger(Events.SUBTITLE_FRAG_PROCESSED, {\n          success: false,\n          frag: frag,\n          error,\n        });\n      },\n    );\n  }\n\n  private _fallbackToIMSC1(frag: Fragment, payload: ArrayBuffer) {\n    // If textCodec is unknown, try parsing as IMSC1. Set textCodec based on the result\n    const trackPlaylistMedia = this.tracks[frag.level];\n    if (!trackPlaylistMedia.textCodec) {\n      parseIMSC1(\n        payload,\n        this.initPTS[frag.cc],\n        () => {\n          trackPlaylistMedia.textCodec = IMSC1_CODEC;\n          this._parseIMSC1(frag, payload);\n        },\n        () => {\n          trackPlaylistMedia.textCodec = 'wvtt';\n        },\n      );\n    }\n  }\n\n  private _appendCues(cues: VTTCue[], fragLevel: number) {\n    const hls = this.hls;\n    if (this.config.renderTextTracksNatively) {\n      const textTrack = this.textTracks[fragLevel];\n      // WebVTTParser.parse is an async method and if the currently selected text track mode is set to \"disabled\"\n      // before parsing is done then don't try to access currentTrack.cues.getCueById as cues will be null\n      // and trying to access getCueById method of cues will throw an exception\n      // Because we check if the mode is disabled, we can force check `cues` below. They can't be null.\n      if (!textTrack || textTrack.mode === 'disabled') {\n        return;\n      }\n      cues.forEach((cue) => addCueToTrack(textTrack, cue));\n    } else {\n      const currentTrack = this.tracks[fragLevel];\n      if (!currentTrack) {\n        return;\n      }\n      const track = currentTrack.default ? 'default' : 'subtitles' + fragLevel;\n      hls.trigger(Events.CUES_PARSED, { type: 'subtitles', cues, track });\n    }\n  }\n\n  private onFragDecrypted(\n    event: Events.FRAG_DECRYPTED,\n    data: FragDecryptedData,\n  ) {\n    const { frag } = data;\n    if (frag.type === PlaylistLevelType.SUBTITLE) {\n      this.onFragLoaded(Events.FRAG_LOADED, data as unknown as FragLoadedData);\n    }\n  }\n\n  private onSubtitleTracksCleared() {\n    this.tracks = [];\n    this.captionsTracks = {};\n  }\n\n  private onFragParsingUserdata(\n    event: Events.FRAG_PARSING_USERDATA,\n    data: FragParsingUserdataData,\n  ) {\n    this.initCea608Parsers();\n    const { cea608Parser1, cea608Parser2 } = this;\n    if (!this.enabled || !cea608Parser1 || !cea608Parser2) {\n      return;\n    }\n    const { frag, samples } = data;\n    if (\n      frag.type === PlaylistLevelType.MAIN &&\n      this.closedCaptionsForLevel(frag) === 'NONE'\n    ) {\n      return;\n    }\n    // If the event contains captions (found in the bytes property), push all bytes into the parser immediately\n    // It will create the proper timestamps based on the PTS value\n    for (let i = 0; i < samples.length; i++) {\n      const ccBytes = samples[i].bytes;\n      if (ccBytes) {\n        const ccdatas = this.extractCea608Data(ccBytes);\n        cea608Parser1.addData(samples[i].pts, ccdatas[0]);\n        cea608Parser2.addData(samples[i].pts, ccdatas[1]);\n      }\n    }\n  }\n\n  onBufferFlushing(\n    event: Events.BUFFER_FLUSHING,\n    { startOffset, endOffset, endOffsetSubtitles, type }: BufferFlushingData,\n  ) {\n    const { media } = this;\n    if (!media || media.currentTime < endOffset) {\n      return;\n    }\n    // Clear 608 caption cues from the captions TextTracks when the video back buffer is flushed\n    // Forward cues are never removed because we can loose streamed 608 content from recent fragments\n    if (!type || type === 'video') {\n      const { captionsTracks } = this;\n      Object.keys(captionsTracks).forEach((trackName) =>\n        removeCuesInRange(captionsTracks[trackName], startOffset, endOffset),\n      );\n    }\n    if (this.config.renderTextTracksNatively) {\n      // Clear VTT/IMSC1 subtitle cues from the subtitle TextTracks when the back buffer is flushed\n      if (startOffset === 0 && endOffsetSubtitles !== undefined) {\n        const { textTracks } = this;\n        Object.keys(textTracks).forEach((trackName) =>\n          removeCuesInRange(\n            textTracks[trackName],\n            startOffset,\n            endOffsetSubtitles,\n          ),\n        );\n      }\n    }\n  }\n\n  private extractCea608Data(byteArray: Uint8Array): number[][] {\n    const actualCCBytes: number[][] = [[], []];\n    const count = byteArray[0] & 0x1f;\n    let position = 2;\n\n    for (let j = 0; j < count; j++) {\n      const tmpByte = byteArray[position++];\n      const ccbyte1 = 0x7f & byteArray[position++];\n      const ccbyte2 = 0x7f & byteArray[position++];\n      if (ccbyte1 === 0 && ccbyte2 === 0) {\n        continue;\n      }\n      const ccValid = (0x04 & tmpByte) !== 0; // Support all four channels\n      if (ccValid) {\n        const ccType = 0x03 & tmpByte;\n        if (\n          0x00 /* CEA608 field1*/ === ccType ||\n          0x01 /* CEA608 field2*/ === ccType\n        ) {\n          // Exclude CEA708 CC data.\n          actualCCBytes[ccType].push(ccbyte1);\n          actualCCBytes[ccType].push(ccbyte2);\n        }\n      }\n    }\n    return actualCCBytes;\n  }\n}\n\nfunction captionsOrSubtitlesFromCharacteristics(\n  track: Pick<MediaPlaylist, 'name' | 'lang' | 'attrs' | 'characteristics'>,\n): TextTrackKind {\n  if (track.characteristics) {\n    if (\n      /transcribes-spoken-dialog/gi.test(track.characteristics) &&\n      /describes-music-and-sound/gi.test(track.characteristics)\n    ) {\n      return 'captions';\n    }\n  }\n\n  return 'subtitles';\n}\n\nfunction canReuseVttTextTrack(\n  inUseTrack: TextTrack | null,\n  manifestTrack: Pick<\n    MediaPlaylist,\n    'name' | 'lang' | 'attrs' | 'characteristics'\n  >,\n): boolean {\n  return (\n    !!inUseTrack &&\n    inUseTrack.kind === captionsOrSubtitlesFromCharacteristics(manifestTrack) &&\n    subtitleTrackMatchesTextTrack(manifestTrack, inUseTrack)\n  );\n}\n\nfunction intersection(x1: number, x2: number, y1: number, y2: number): number {\n  return Math.min(x2, y2) - Math.max(x1, y1);\n}\n\nfunction newVTTCCs(): VTTCCs {\n  return {\n    ccOffset: 0,\n    presentationOffset: 0,\n    0: {\n      start: 0,\n      prevCC: -1,\n      new: true,\n    },\n  };\n}\n", "/*\n * cap stream level to media size dimension controller\n */\n\nimport { Events } from '../events';\nimport type { Level } from '../types/level';\nimport type {\n  ManifestParsedData,\n  BufferCodecsData,\n  MediaAttachingData,\n  FPSDropLevelCappingData,\n  LevelsUpdatedData,\n} from '../types/events';\nimport StreamController from './stream-controller';\nimport { logger } from '../utils/logger';\nimport type { ComponentAPI } from '../types/component-api';\nimport type Hls from '../hls';\n\ntype RestrictedLevel = { width: number; height: number; bitrate: number };\nclass CapLevelController implements ComponentAPI {\n  private hls: Hls;\n  private autoLevelCapping: number;\n  private firstLevel: number;\n  private media: HTMLVideoElement | null;\n  private restrictedLevels: RestrictedLevel[];\n  private timer: number | undefined;\n  private clientRect: { width: number; height: number } | null;\n  private streamController?: StreamController;\n\n  constructor(hls: Hls) {\n    this.hls = hls;\n    this.autoLevelCapping = Number.POSITIVE_INFINITY;\n    this.firstLevel = -1;\n    this.media = null;\n    this.restrictedLevels = [];\n    this.timer = undefined;\n    this.clientRect = null;\n\n    this.registerListeners();\n  }\n\n  public setStreamController(streamController: StreamController) {\n    this.streamController = streamController;\n  }\n\n  public destroy() {\n    if (this.hls) {\n      this.unregisterListener();\n    }\n    if (this.timer) {\n      this.stopCapping();\n    }\n    this.media = null;\n    this.clientRect = null;\n    // @ts-ignore\n    this.hls = this.streamController = null;\n  }\n\n  protected registerListeners() {\n    const { hls } = this;\n    hls.on(Events.FPS_DROP_LEVEL_CAPPING, this.onFpsDropLevelCapping, this);\n    hls.on(Events.MEDIA_ATTACHING, this.onMediaAttaching, this);\n    hls.on(Events.MANIFEST_PARSED, this.onManifestParsed, this);\n    hls.on(Events.LEVELS_UPDATED, this.onLevelsUpdated, this);\n    hls.on(Events.BUFFER_CODECS, this.onBufferCodecs, this);\n    hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n  }\n\n  protected unregisterListener() {\n    const { hls } = this;\n    hls.off(Events.FPS_DROP_LEVEL_CAPPING, this.onFpsDropLevelCapping, this);\n    hls.off(Events.MEDIA_ATTACHING, this.onMediaAttaching, this);\n    hls.off(Events.MANIFEST_PARSED, this.onManifestParsed, this);\n    hls.off(Events.LEVELS_UPDATED, this.onLevelsUpdated, this);\n    hls.off(Events.BUFFER_CODECS, this.onBufferCodecs, this);\n    hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n  }\n\n  protected onFpsDropLevelCapping(\n    event: Events.FPS_DROP_LEVEL_CAPPING,\n    data: FPSDropLevelCappingData,\n  ) {\n    // Don't add a restricted level more than once\n    const level = this.hls.levels[data.droppedLevel];\n    if (this.isLevelAllowed(level)) {\n      this.restrictedLevels.push({\n        bitrate: level.bitrate,\n        height: level.height,\n        width: level.width,\n      });\n    }\n  }\n\n  protected onMediaAttaching(\n    event: Events.MEDIA_ATTACHING,\n    data: MediaAttachingData,\n  ) {\n    this.media = data.media instanceof HTMLVideoElement ? data.media : null;\n    this.clientRect = null;\n    if (this.timer && this.hls.levels.length) {\n      this.detectPlayerSize();\n    }\n  }\n\n  protected onManifestParsed(\n    event: Events.MANIFEST_PARSED,\n    data: ManifestParsedData,\n  ) {\n    const hls = this.hls;\n    this.restrictedLevels = [];\n    this.firstLevel = data.firstLevel;\n    if (hls.config.capLevelToPlayerSize && data.video) {\n      // Start capping immediately if the manifest has signaled video codecs\n      this.startCapping();\n    }\n  }\n\n  private onLevelsUpdated(\n    event: Events.LEVELS_UPDATED,\n    data: LevelsUpdatedData,\n  ) {\n    if (this.timer && Number.isFinite(this.autoLevelCapping)) {\n      this.detectPlayerSize();\n    }\n  }\n\n  // Only activate capping when playing a video stream; otherwise, multi-bitrate audio-only streams will be restricted\n  // to the first level\n  protected onBufferCodecs(\n    event: Events.BUFFER_CODECS,\n    data: BufferCodecsData,\n  ) {\n    const hls = this.hls;\n    if (hls.config.capLevelToPlayerSize && data.video) {\n      // If the manifest did not signal a video codec capping has been deferred until we're certain video is present\n      this.startCapping();\n    }\n  }\n\n  protected onMediaDetaching() {\n    this.stopCapping();\n  }\n\n  detectPlayerSize() {\n    if (this.media) {\n      if (this.mediaHeight <= 0 || this.mediaWidth <= 0) {\n        this.clientRect = null;\n        return;\n      }\n      const levels = this.hls.levels;\n      if (levels.length) {\n        const hls = this.hls;\n        const maxLevel = this.getMaxLevel(levels.length - 1);\n        if (maxLevel !== this.autoLevelCapping) {\n          logger.log(\n            `Setting autoLevelCapping to ${maxLevel}: ${levels[maxLevel].height}p@${levels[maxLevel].bitrate} for media ${this.mediaWidth}x${this.mediaHeight}`,\n          );\n        }\n        hls.autoLevelCapping = maxLevel;\n        if (\n          hls.autoLevelCapping > this.autoLevelCapping &&\n          this.streamController\n        ) {\n          // if auto level capping has a higher value for the previous one, flush the buffer using nextLevelSwitch\n          // usually happen when the user go to the fullscreen mode.\n          this.streamController.nextLevelSwitch();\n        }\n        this.autoLevelCapping = hls.autoLevelCapping;\n      }\n    }\n  }\n\n  /*\n   * returns level should be the one with the dimensions equal or greater than the media (player) dimensions (so the video will be downscaled)\n   */\n  getMaxLevel(capLevelIndex: number): number {\n    const levels = this.hls.levels;\n    if (!levels.length) {\n      return -1;\n    }\n\n    const validLevels = levels.filter(\n      (level, index) => this.isLevelAllowed(level) && index <= capLevelIndex,\n    );\n\n    this.clientRect = null;\n    return CapLevelController.getMaxLevelByMediaSize(\n      validLevels,\n      this.mediaWidth,\n      this.mediaHeight,\n    );\n  }\n\n  startCapping() {\n    if (this.timer) {\n      // Don't reset capping if started twice; this can happen if the manifest signals a video codec\n      return;\n    }\n    this.autoLevelCapping = Number.POSITIVE_INFINITY;\n    self.clearInterval(this.timer);\n    this.timer = self.setInterval(this.detectPlayerSize.bind(this), 1000);\n    this.detectPlayerSize();\n  }\n\n  stopCapping() {\n    this.restrictedLevels = [];\n    this.firstLevel = -1;\n    this.autoLevelCapping = Number.POSITIVE_INFINITY;\n    if (this.timer) {\n      self.clearInterval(this.timer);\n      this.timer = undefined;\n    }\n  }\n\n  getDimensions(): { width: number; height: number } {\n    if (this.clientRect) {\n      return this.clientRect;\n    }\n    const media = this.media;\n    const boundsRect = {\n      width: 0,\n      height: 0,\n    };\n\n    if (media) {\n      const clientRect = media.getBoundingClientRect();\n      boundsRect.width = clientRect.width;\n      boundsRect.height = clientRect.height;\n      if (!boundsRect.width && !boundsRect.height) {\n        // When the media element has no width or height (equivalent to not being in the DOM),\n        // then use its width and height attributes (media.width, media.height)\n        boundsRect.width =\n          clientRect.right - clientRect.left || media.width || 0;\n        boundsRect.height =\n          clientRect.bottom - clientRect.top || media.height || 0;\n      }\n    }\n    this.clientRect = boundsRect;\n    return boundsRect;\n  }\n\n  get mediaWidth(): number {\n    return this.getDimensions().width * this.contentScaleFactor;\n  }\n\n  get mediaHeight(): number {\n    return this.getDimensions().height * this.contentScaleFactor;\n  }\n\n  get contentScaleFactor(): number {\n    let pixelRatio = 1;\n    if (!this.hls.config.ignoreDevicePixelRatio) {\n      try {\n        pixelRatio = self.devicePixelRatio;\n      } catch (e) {\n        /* no-op */\n      }\n    }\n\n    return pixelRatio;\n  }\n\n  private isLevelAllowed(level: Level): boolean {\n    const restrictedLevels = this.restrictedLevels;\n    return !restrictedLevels.some((restrictedLevel) => {\n      return (\n        level.bitrate === restrictedLevel.bitrate &&\n        level.width === restrictedLevel.width &&\n        level.height === restrictedLevel.height\n      );\n    });\n  }\n\n  static getMaxLevelByMediaSize(\n    levels: Array<Level>,\n    width: number,\n    height: number,\n  ): number {\n    if (!levels?.length) {\n      return -1;\n    }\n\n    // Levels can have the same dimensions but differing bandwidths - since levels are ordered, we can look to the next\n    // to determine whether we've chosen the greatest bandwidth for the media's dimensions\n    const atGreatestBandwidth = (\n      curLevel: Level,\n      nextLevel: Level | undefined,\n    ) => {\n      if (!nextLevel) {\n        return true;\n      }\n\n      return (\n        curLevel.width !== nextLevel.width ||\n        curLevel.height !== nextLevel.height\n      );\n    };\n\n    // If we run through the loop without breaking, the media's dimensions are greater than every level, so default to\n    // the max level\n    let maxLevelIndex = levels.length - 1;\n    // Prevent changes in aspect-ratio from causing capping to toggle back and forth\n    const squareSize = Math.max(width, height);\n    for (let i = 0; i < levels.length; i += 1) {\n      const level = levels[i];\n      if (\n        (level.width >= squareSize || level.height >= squareSize) &&\n        atGreatestBandwidth(level, levels[i + 1])\n      ) {\n        maxLevelIndex = i;\n        break;\n      }\n    }\n\n    return maxLevelIndex;\n  }\n}\n\nexport default CapLevelController;\n", "import { Events } from '../events';\nimport { logger } from '../utils/logger';\nimport type { ComponentAPI } from '../types/component-api';\nimport type Hls from '../hls';\nimport type { MediaAttachingData } from '../types/events';\nimport StreamController from './stream-controller';\n\nclass FPSController implements ComponentAPI {\n  private hls: Hls;\n  private isVideoPlaybackQualityAvailable: boolean = false;\n  private timer?: number;\n  private media: HTMLVideoElement | null = null;\n  private lastTime: any;\n  private lastDroppedFrames: number = 0;\n  private lastDecodedFrames: number = 0;\n  // stream controller must be provided as a dependency!\n  private streamController!: StreamController;\n\n  constructor(hls: Hls) {\n    this.hls = hls;\n\n    this.registerListeners();\n  }\n\n  public setStreamController(streamController: StreamController) {\n    this.streamController = streamController;\n  }\n\n  protected registerListeners() {\n    this.hls.on(Events.MEDIA_ATTACHING, this.onMediaAttaching, this);\n  }\n\n  protected unregisterListeners() {\n    this.hls.off(Events.MEDIA_ATTACHING, this.onMediaAttaching, this);\n  }\n\n  destroy() {\n    if (this.timer) {\n      clearInterval(this.timer);\n    }\n\n    this.unregisterListeners();\n    this.isVideoPlaybackQualityAvailable = false;\n    this.media = null;\n  }\n\n  protected onMediaAttaching(\n    event: Events.MEDIA_ATTACHING,\n    data: MediaAttachingData,\n  ) {\n    const config = this.hls.config;\n    if (config.capLevelOnFPSDrop) {\n      const media =\n        data.media instanceof self.HTMLVideoElement ? data.media : null;\n      this.media = media;\n      if (media && typeof media.getVideoPlaybackQuality === 'function') {\n        this.isVideoPlaybackQualityAvailable = true;\n      }\n\n      self.clearInterval(this.timer);\n      this.timer = self.setInterval(\n        this.checkFPSInterval.bind(this),\n        config.fpsDroppedMonitoringPeriod,\n      );\n    }\n  }\n\n  checkFPS(\n    video: HTMLVideoElement,\n    decodedFrames: number,\n    droppedFrames: number,\n  ) {\n    const currentTime = performance.now();\n    if (decodedFrames) {\n      if (this.lastTime) {\n        const currentPeriod = currentTime - this.lastTime;\n        const currentDropped = droppedFrames - this.lastDroppedFrames;\n        const currentDecoded = decodedFrames - this.lastDecodedFrames;\n        const droppedFPS = (1000 * currentDropped) / currentPeriod;\n        const hls = this.hls;\n        hls.trigger(Events.FPS_DROP, {\n          currentDropped: currentDropped,\n          currentDecoded: currentDecoded,\n          totalDroppedFrames: droppedFrames,\n        });\n        if (droppedFPS > 0) {\n          // logger.log('checkFPS : droppedFPS/decodedFPS:' + droppedFPS/(1000 * currentDecoded / currentPeriod));\n          if (\n            currentDropped >\n            hls.config.fpsDroppedMonitoringThreshold * currentDecoded\n          ) {\n            let currentLevel = hls.currentLevel;\n            logger.warn(\n              'drop FPS ratio greater than max allowed value for currentLevel: ' +\n                currentLevel,\n            );\n            if (\n              currentLevel > 0 &&\n              (hls.autoLevelCapping === -1 ||\n                hls.autoLevelCapping >= currentLevel)\n            ) {\n              currentLevel = currentLevel - 1;\n              hls.trigger(Events.FPS_DROP_LEVEL_CAPPING, {\n                level: currentLevel,\n                droppedLevel: hls.currentLevel,\n              });\n              hls.autoLevelCapping = currentLevel;\n              this.streamController.nextLevelSwitch();\n            }\n          }\n        }\n      }\n      this.lastTime = currentTime;\n      this.lastDroppedFrames = droppedFrames;\n      this.lastDecodedFrames = decodedFrames;\n    }\n  }\n\n  checkFPSInterval() {\n    const video = this.media;\n    if (video) {\n      if (this.isVideoPlaybackQualityAvailable) {\n        const videoPlaybackQuality = video.getVideoPlaybackQuality();\n        this.checkFPS(\n          video,\n          videoPlaybackQuality.totalVideoFrames,\n          videoPlaybackQuality.droppedVideoFrames,\n        );\n      } else {\n        // HTMLVideoElement doesn't include the webkit types\n        this.checkFPS(\n          video,\n          (video as any).webkitDecodedFrameCount as number,\n          (video as any).webkitDroppedFrameCount as number,\n        );\n      }\n    }\n  }\n}\n\nexport default FPSController;\n", "/**\n * @author Stephan Hesse <disparat@gmail.com> | <tchakabam@gmail.com>\n *\n * DRM support for Hls.js\n */\nimport { Events } from '../events';\nimport { ErrorTypes, ErrorDetails } from '../errors';\nimport { logger } from '../utils/logger';\nimport {\n  getKeySystemsForConfig,\n  getSupportedMediaKeySystemConfigurations,\n  keySystemDomainToKeySystemFormat as keySystemToKeySystemFormat,\n  KeySystemFormats,\n  keySystemFormatToKeySystemDomain,\n  KeySystemIds,\n  keySystemIdToKeySystemDomain,\n  KeySystems,\n  requestMediaKeySystemAccess,\n} from '../utils/mediakeys-helper';\nimport { strToUtf8array } from '../utils/keysystem-util';\nimport { base64Decode } from '../utils/numeric-encoding-utils';\nimport { DecryptData, LevelKey } from '../loader/level-key';\nimport Hex from '../utils/hex';\nimport {\n  bin2str,\n  parseMultiPssh,\n  parseSinf,\n  PsshData,\n  PsshInvalidResult,\n} from '../utils/mp4-tools';\nimport { EventEmitter } from 'eventemitter3';\nimport type Hls from '../hls';\nimport type { ComponentAPI } from '../types/component-api';\nimport type {\n  MediaAttachedData,\n  KeyLoadedData,\n  ErrorData,\n  ManifestLoadedData,\n} from '../types/events';\nimport type { EMEControllerConfig, HlsConfig, LoadPolicy } from '../config';\nimport type { Fragment } from '../loader/fragment';\nimport type {\n  Loader,\n  LoaderCallbacks,\n  LoaderConfiguration,\n  LoaderContext,\n} from '../types/loader';\n\nconst LOGGER_PREFIX = '[eme]';\n\ninterface KeySystemAccessPromises {\n  keySystemAccess: Promise<MediaKeySystemAccess>;\n  mediaKeys?: Promise<MediaKeys>;\n  certificate?: Promise<BufferSource | void>;\n}\n\nexport interface MediaKeySessionContext {\n  keySystem: KeySystems;\n  mediaKeys: MediaKeys;\n  decryptdata: LevelKey;\n  mediaKeysSession: MediaKeySession;\n  keyStatus: MediaKeyStatus;\n  licenseXhr?: XMLHttpRequest;\n  _onmessage?: (this: MediaKeySession, ev: MediaKeyMessageEvent) => any;\n  _onkeystatuseschange?: (this: MediaKeySession, ev: Event) => any;\n}\n\n/**\n * Controller to deal with encrypted media extensions (EME)\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Encrypted_Media_Extensions_API\n *\n * @class\n * @constructor\n */\nclass EMEController implements ComponentAPI {\n  public static CDMCleanupPromise: Promise<void> | void;\n\n  private readonly hls: Hls;\n  private readonly config: EMEControllerConfig & {\n    loader: { new (confg: HlsConfig): Loader<LoaderContext> };\n    certLoadPolicy: LoadPolicy;\n    keyLoadPolicy: LoadPolicy;\n  };\n  private media: HTMLMediaElement | null = null;\n  private keyFormatPromise: Promise<KeySystemFormats> | null = null;\n  private keySystemAccessPromises: {\n    [keysystem: string]: KeySystemAccessPromises;\n  } = {};\n  private _requestLicenseFailureCount: number = 0;\n  private mediaKeySessions: MediaKeySessionContext[] = [];\n  private keyIdToKeySessionPromise: {\n    [keyId: string]: Promise<MediaKeySessionContext>;\n  } = {};\n  private setMediaKeysQueue: Promise<void>[] = EMEController.CDMCleanupPromise\n    ? [EMEController.CDMCleanupPromise]\n    : [];\n  private onMediaEncrypted = this._onMediaEncrypted.bind(this);\n  private onWaitingForKey = this._onWaitingForKey.bind(this);\n\n  private debug: (msg: any) => void = logger.debug.bind(logger, LOGGER_PREFIX);\n  private log: (msg: any) => void = logger.log.bind(logger, LOGGER_PREFIX);\n  private warn: (msg: any) => void = logger.warn.bind(logger, LOGGER_PREFIX);\n  private error: (msg: any) => void = logger.error.bind(logger, LOGGER_PREFIX);\n\n  constructor(hls: Hls) {\n    this.hls = hls;\n    this.config = hls.config;\n    this.registerListeners();\n  }\n\n  public destroy() {\n    this.unregisterListeners();\n    this.onMediaDetached();\n    // Remove any references that could be held in config options or callbacks\n    const config = this.config;\n    config.requestMediaKeySystemAccessFunc = null;\n    config.licenseXhrSetup = config.licenseResponseCallback = undefined;\n    config.drmSystems = config.drmSystemOptions = {};\n    // @ts-ignore\n    this.hls =\n      this.onMediaEncrypted =\n      this.onWaitingForKey =\n      this.keyIdToKeySessionPromise =\n        null as any;\n    // @ts-ignore\n    this.config = null;\n  }\n\n  private registerListeners() {\n    this.hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n    this.hls.on(Events.MEDIA_DETACHED, this.onMediaDetached, this);\n    this.hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    this.hls.on(Events.MANIFEST_LOADED, this.onManifestLoaded, this);\n  }\n\n  private unregisterListeners() {\n    this.hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n    this.hls.off(Events.MEDIA_DETACHED, this.onMediaDetached, this);\n    this.hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    this.hls.off(Events.MANIFEST_LOADED, this.onManifestLoaded, this);\n  }\n\n  private getLicenseServerUrl(keySystem: KeySystems): string | never {\n    const { drmSystems, widevineLicenseUrl } = this.config;\n    const keySystemConfiguration = drmSystems[keySystem];\n\n    if (keySystemConfiguration) {\n      return keySystemConfiguration.licenseUrl;\n    }\n\n    // For backward compatibility\n    if (keySystem === KeySystems.WIDEVINE && widevineLicenseUrl) {\n      return widevineLicenseUrl;\n    }\n\n    throw new Error(\n      `no license server URL configured for key-system \"${keySystem}\"`,\n    );\n  }\n\n  private getServerCertificateUrl(keySystem: KeySystems): string | void {\n    const { drmSystems } = this.config;\n    const keySystemConfiguration = drmSystems[keySystem];\n\n    if (keySystemConfiguration) {\n      return keySystemConfiguration.serverCertificateUrl;\n    } else {\n      this.log(`No Server Certificate in config.drmSystems[\"${keySystem}\"]`);\n    }\n  }\n\n  private attemptKeySystemAccess(\n    keySystemsToAttempt: KeySystems[],\n  ): Promise<{ keySystem: KeySystems; mediaKeys: MediaKeys }> {\n    const levels = this.hls.levels;\n    const uniqueCodec = (value: string | undefined, i, a): value is string =>\n      !!value && a.indexOf(value) === i;\n    const audioCodecs = levels\n      .map((level) => level.audioCodec)\n      .filter(uniqueCodec);\n    const videoCodecs = levels\n      .map((level) => level.videoCodec)\n      .filter(uniqueCodec);\n    if (audioCodecs.length + videoCodecs.length === 0) {\n      videoCodecs.push('avc1.42e01e');\n    }\n\n    return new Promise(\n      (\n        resolve: (result: {\n          keySystem: KeySystems;\n          mediaKeys: MediaKeys;\n        }) => void,\n        reject: (Error) => void,\n      ) => {\n        const attempt = (keySystems) => {\n          const keySystem = keySystems.shift();\n          this.getMediaKeysPromise(keySystem, audioCodecs, videoCodecs)\n            .then((mediaKeys) => resolve({ keySystem, mediaKeys }))\n            .catch((error) => {\n              if (keySystems.length) {\n                attempt(keySystems);\n              } else if (error instanceof EMEKeyError) {\n                reject(error);\n              } else {\n                reject(\n                  new EMEKeyError(\n                    {\n                      type: ErrorTypes.KEY_SYSTEM_ERROR,\n                      details: ErrorDetails.KEY_SYSTEM_NO_ACCESS,\n                      error,\n                      fatal: true,\n                    },\n                    error.message,\n                  ),\n                );\n              }\n            });\n        };\n        attempt(keySystemsToAttempt);\n      },\n    );\n  }\n\n  private requestMediaKeySystemAccess(\n    keySystem: KeySystems,\n    supportedConfigurations: MediaKeySystemConfiguration[],\n  ): Promise<MediaKeySystemAccess> {\n    const { requestMediaKeySystemAccessFunc } = this.config;\n    if (!(typeof requestMediaKeySystemAccessFunc === 'function')) {\n      let errMessage = `Configured requestMediaKeySystemAccess is not a function ${requestMediaKeySystemAccessFunc}`;\n      if (\n        requestMediaKeySystemAccess === null &&\n        self.location.protocol === 'http:'\n      ) {\n        errMessage = `navigator.requestMediaKeySystemAccess is not available over insecure protocol ${location.protocol}`;\n      }\n      return Promise.reject(new Error(errMessage));\n    }\n\n    return requestMediaKeySystemAccessFunc(keySystem, supportedConfigurations);\n  }\n\n  private getMediaKeysPromise(\n    keySystem: KeySystems,\n    audioCodecs: string[],\n    videoCodecs: string[],\n  ): Promise<MediaKeys> {\n    // This can throw, but is caught in event handler callpath\n    const mediaKeySystemConfigs = getSupportedMediaKeySystemConfigurations(\n      keySystem,\n      audioCodecs,\n      videoCodecs,\n      this.config.drmSystemOptions,\n    );\n    const keySystemAccessPromises: KeySystemAccessPromises =\n      this.keySystemAccessPromises[keySystem];\n    let keySystemAccess = keySystemAccessPromises?.keySystemAccess;\n    if (!keySystemAccess) {\n      this.log(\n        `Requesting encrypted media \"${keySystem}\" key-system access with config: ${JSON.stringify(\n          mediaKeySystemConfigs,\n        )}`,\n      );\n      keySystemAccess = this.requestMediaKeySystemAccess(\n        keySystem,\n        mediaKeySystemConfigs,\n      );\n      const keySystemAccessPromises: KeySystemAccessPromises =\n        (this.keySystemAccessPromises[keySystem] = {\n          keySystemAccess,\n        });\n      keySystemAccess.catch((error) => {\n        this.log(\n          `Failed to obtain access to key-system \"${keySystem}\": ${error}`,\n        );\n      });\n      return keySystemAccess.then((mediaKeySystemAccess) => {\n        this.log(\n          `Access for key-system \"${mediaKeySystemAccess.keySystem}\" obtained`,\n        );\n\n        const certificateRequest = this.fetchServerCertificate(keySystem);\n\n        this.log(`Create media-keys for \"${keySystem}\"`);\n        keySystemAccessPromises.mediaKeys = mediaKeySystemAccess\n          .createMediaKeys()\n          .then((mediaKeys) => {\n            this.log(`Media-keys created for \"${keySystem}\"`);\n            return certificateRequest.then((certificate) => {\n              if (certificate) {\n                return this.setMediaKeysServerCertificate(\n                  mediaKeys,\n                  keySystem,\n                  certificate,\n                );\n              }\n              return mediaKeys;\n            });\n          });\n\n        keySystemAccessPromises.mediaKeys.catch((error) => {\n          this.error(\n            `Failed to create media-keys for \"${keySystem}\"}: ${error}`,\n          );\n        });\n\n        return keySystemAccessPromises.mediaKeys;\n      });\n    }\n    return keySystemAccess.then(() => keySystemAccessPromises.mediaKeys!);\n  }\n\n  private createMediaKeySessionContext({\n    decryptdata,\n    keySystem,\n    mediaKeys,\n  }: {\n    decryptdata: LevelKey;\n    keySystem: KeySystems;\n    mediaKeys: MediaKeys;\n  }): MediaKeySessionContext {\n    this.log(\n      `Creating key-system session \"${keySystem}\" keyId: ${Hex.hexDump(\n        decryptdata.keyId! || [],\n      )}`,\n    );\n\n    const mediaKeysSession = mediaKeys.createSession();\n\n    const mediaKeySessionContext: MediaKeySessionContext = {\n      decryptdata,\n      keySystem,\n      mediaKeys,\n      mediaKeysSession,\n      keyStatus: 'status-pending',\n    };\n\n    this.mediaKeySessions.push(mediaKeySessionContext);\n\n    return mediaKeySessionContext;\n  }\n\n  private renewKeySession(mediaKeySessionContext: MediaKeySessionContext) {\n    const decryptdata = mediaKeySessionContext.decryptdata;\n    if (decryptdata.pssh) {\n      const keySessionContext = this.createMediaKeySessionContext(\n        mediaKeySessionContext,\n      );\n      const keyId = this.getKeyIdString(decryptdata);\n      const scheme = 'cenc';\n      this.keyIdToKeySessionPromise[keyId] =\n        this.generateRequestWithPreferredKeySession(\n          keySessionContext,\n          scheme,\n          decryptdata.pssh,\n          'expired',\n        );\n    } else {\n      this.warn(`Could not renew expired session. Missing pssh initData.`);\n    }\n    this.removeSession(mediaKeySessionContext);\n  }\n\n  private getKeyIdString(decryptdata: DecryptData | undefined): string | never {\n    if (!decryptdata) {\n      throw new Error('Could not read keyId of undefined decryptdata');\n    }\n    if (decryptdata.keyId === null) {\n      throw new Error('keyId is null');\n    }\n    return Hex.hexDump(decryptdata.keyId);\n  }\n\n  private updateKeySession(\n    mediaKeySessionContext: MediaKeySessionContext,\n    data: Uint8Array,\n  ): Promise<void> {\n    const keySession = mediaKeySessionContext.mediaKeysSession;\n    this.log(\n      `Updating key-session \"${keySession.sessionId}\" for keyID ${Hex.hexDump(\n        mediaKeySessionContext.decryptdata?.keyId! || [],\n      )}\n      } (data length: ${data ? data.byteLength : data})`,\n    );\n    return keySession.update(data);\n  }\n\n  public selectKeySystemFormat(frag: Fragment): Promise<KeySystemFormats> {\n    const keyFormats = Object.keys(frag.levelkeys || {}) as KeySystemFormats[];\n    if (!this.keyFormatPromise) {\n      this.log(\n        `Selecting key-system from fragment (sn: ${frag.sn} ${frag.type}: ${\n          frag.level\n        }) key formats ${keyFormats.join(', ')}`,\n      );\n      this.keyFormatPromise = this.getKeyFormatPromise(keyFormats);\n    }\n    return this.keyFormatPromise;\n  }\n\n  private getKeyFormatPromise(\n    keyFormats: KeySystemFormats[],\n  ): Promise<KeySystemFormats> {\n    return new Promise((resolve, reject) => {\n      const keySystemsInConfig = getKeySystemsForConfig(this.config);\n      const keySystemsToAttempt = keyFormats\n        .map(keySystemFormatToKeySystemDomain)\n        .filter(\n          (value) => !!value && keySystemsInConfig.indexOf(value) !== -1,\n        ) as any as KeySystems[];\n      return this.getKeySystemSelectionPromise(keySystemsToAttempt)\n        .then(({ keySystem }) => {\n          const keySystemFormat = keySystemToKeySystemFormat(keySystem);\n          if (keySystemFormat) {\n            resolve(keySystemFormat);\n          } else {\n            reject(\n              new Error(`Unable to find format for key-system \"${keySystem}\"`),\n            );\n          }\n        })\n        .catch(reject);\n    });\n  }\n\n  public loadKey(data: KeyLoadedData): Promise<MediaKeySessionContext> {\n    const decryptdata = data.keyInfo.decryptdata;\n\n    const keyId = this.getKeyIdString(decryptdata);\n    const keyDetails = `(keyId: ${keyId} format: \"${decryptdata.keyFormat}\" method: ${decryptdata.method} uri: ${decryptdata.uri})`;\n\n    this.log(`Starting session for key ${keyDetails}`);\n\n    let keySessionContextPromise = this.keyIdToKeySessionPromise[keyId];\n    if (!keySessionContextPromise) {\n      keySessionContextPromise = this.keyIdToKeySessionPromise[keyId] =\n        this.getKeySystemForKeyPromise(decryptdata).then(\n          ({ keySystem, mediaKeys }) => {\n            this.throwIfDestroyed();\n            this.log(\n              `Handle encrypted media sn: ${data.frag.sn} ${data.frag.type}: ${data.frag.level} using key ${keyDetails}`,\n            );\n\n            return this.attemptSetMediaKeys(keySystem, mediaKeys).then(() => {\n              this.throwIfDestroyed();\n              const keySessionContext = this.createMediaKeySessionContext({\n                keySystem,\n                mediaKeys,\n                decryptdata,\n              });\n              const scheme = 'cenc';\n              return this.generateRequestWithPreferredKeySession(\n                keySessionContext,\n                scheme,\n                decryptdata.pssh,\n                'playlist-key',\n              );\n            });\n          },\n        );\n\n      keySessionContextPromise.catch((error) => this.handleError(error));\n    }\n\n    return keySessionContextPromise;\n  }\n\n  private throwIfDestroyed(message = 'Invalid state'): void | never {\n    if (!this.hls) {\n      throw new Error('invalid state');\n    }\n  }\n\n  private handleError(error: EMEKeyError | Error) {\n    if (!this.hls) {\n      return;\n    }\n    this.error(error.message);\n    if (error instanceof EMEKeyError) {\n      this.hls.trigger(Events.ERROR, error.data);\n    } else {\n      this.hls.trigger(Events.ERROR, {\n        type: ErrorTypes.KEY_SYSTEM_ERROR,\n        details: ErrorDetails.KEY_SYSTEM_NO_KEYS,\n        error,\n        fatal: true,\n      });\n    }\n  }\n\n  private getKeySystemForKeyPromise(\n    decryptdata: LevelKey,\n  ): Promise<{ keySystem: KeySystems; mediaKeys: MediaKeys }> {\n    const keyId = this.getKeyIdString(decryptdata);\n    const mediaKeySessionContext = this.keyIdToKeySessionPromise[keyId];\n    if (!mediaKeySessionContext) {\n      const keySystem = keySystemFormatToKeySystemDomain(\n        decryptdata.keyFormat as KeySystemFormats,\n      );\n      const keySystemsToAttempt = keySystem\n        ? [keySystem]\n        : getKeySystemsForConfig(this.config);\n      return this.attemptKeySystemAccess(keySystemsToAttempt);\n    }\n    return mediaKeySessionContext;\n  }\n\n  private getKeySystemSelectionPromise(\n    keySystemsToAttempt: KeySystems[],\n  ): Promise<{ keySystem: KeySystems; mediaKeys: MediaKeys }> | never {\n    if (!keySystemsToAttempt.length) {\n      keySystemsToAttempt = getKeySystemsForConfig(this.config);\n    }\n    if (keySystemsToAttempt.length === 0) {\n      throw new EMEKeyError(\n        {\n          type: ErrorTypes.KEY_SYSTEM_ERROR,\n          details: ErrorDetails.KEY_SYSTEM_NO_CONFIGURED_LICENSE,\n          fatal: true,\n        },\n        `Missing key-system license configuration options ${JSON.stringify({\n          drmSystems: this.config.drmSystems,\n        })}`,\n      );\n    }\n    return this.attemptKeySystemAccess(keySystemsToAttempt);\n  }\n\n  private _onMediaEncrypted(event: MediaEncryptedEvent) {\n    const { initDataType, initData } = event;\n    const logMessage = `\"${event.type}\" event: init data type: \"${initDataType}\"`;\n    this.debug(logMessage);\n\n    // Ignore event when initData is null\n    if (initData === null) {\n      return;\n    }\n\n    let keyId: Uint8Array | undefined;\n    let keySystemDomain: KeySystems | undefined;\n\n    if (\n      initDataType === 'sinf' &&\n      this.config.drmSystems[KeySystems.FAIRPLAY]\n    ) {\n      // Match sinf keyId to playlist skd://keyId=\n      const json = bin2str(new Uint8Array(initData));\n      try {\n        const sinf = base64Decode(JSON.parse(json).sinf);\n        const tenc = parseSinf(new Uint8Array(sinf));\n        if (!tenc) {\n          throw new Error(\n            `'schm' box missing or not cbcs/cenc with schi > tenc`,\n          );\n        }\n        keyId = tenc.subarray(8, 24);\n        keySystemDomain = KeySystems.FAIRPLAY;\n      } catch (error) {\n        this.warn(`${logMessage} Failed to parse sinf: ${error}`);\n        return;\n      }\n    } else {\n      // Support Widevine clear-lead key-session creation (otherwise depend on playlist keys)\n      const psshResults = parseMultiPssh(initData);\n      const psshInfo = psshResults.filter(\n        (pssh): pssh is PsshData => pssh.systemId === KeySystemIds.WIDEVINE,\n      )[0];\n      if (!psshInfo) {\n        if (\n          psshResults.length === 0 ||\n          psshResults.some((pssh): pssh is PsshInvalidResult => !pssh.systemId)\n        ) {\n          this.warn(`${logMessage} contains incomplete or invalid pssh data`);\n        } else {\n          this.log(\n            `ignoring ${logMessage} for ${(psshResults as PsshData[])\n              .map((pssh) => keySystemIdToKeySystemDomain(pssh.systemId))\n              .join(',')} pssh data in favor of playlist keys`,\n          );\n        }\n        return;\n      }\n      keySystemDomain = keySystemIdToKeySystemDomain(psshInfo.systemId);\n      if (psshInfo.version === 0 && psshInfo.data) {\n        const offset = psshInfo.data.length - 22;\n        keyId = psshInfo.data.subarray(offset, offset + 16);\n      }\n    }\n\n    if (!keySystemDomain || !keyId) {\n      return;\n    }\n\n    const keyIdHex = Hex.hexDump(keyId);\n    const { keyIdToKeySessionPromise, mediaKeySessions } = this;\n\n    let keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex];\n    for (let i = 0; i < mediaKeySessions.length; i++) {\n      // Match playlist key\n      const keyContext = mediaKeySessions[i];\n      const decryptdata = keyContext.decryptdata;\n      if (!decryptdata.keyId) {\n        continue;\n      }\n      const oldKeyIdHex = Hex.hexDump(decryptdata.keyId);\n      if (\n        keyIdHex === oldKeyIdHex ||\n        decryptdata.uri.replace(/-/g, '').indexOf(keyIdHex) !== -1\n      ) {\n        keySessionContextPromise = keyIdToKeySessionPromise[oldKeyIdHex];\n        if (decryptdata.pssh) {\n          break;\n        }\n        delete keyIdToKeySessionPromise[oldKeyIdHex];\n        decryptdata.pssh = new Uint8Array(initData);\n        decryptdata.keyId = keyId;\n        keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] =\n          keySessionContextPromise.then(() => {\n            return this.generateRequestWithPreferredKeySession(\n              keyContext,\n              initDataType,\n              initData,\n              'encrypted-event-key-match',\n            );\n          });\n        break;\n      }\n    }\n\n    if (!keySessionContextPromise) {\n      // Clear-lead key (not encountered in playlist)\n      keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] =\n        this.getKeySystemSelectionPromise([keySystemDomain]).then(\n          ({ keySystem, mediaKeys }) => {\n            this.throwIfDestroyed();\n            const decryptdata = new LevelKey(\n              'ISO-23001-7',\n              keyIdHex,\n              keySystemToKeySystemFormat(keySystem) ?? '',\n            );\n            decryptdata.pssh = new Uint8Array(initData);\n            decryptdata.keyId = keyId as Uint8Array;\n            return this.attemptSetMediaKeys(keySystem, mediaKeys).then(() => {\n              this.throwIfDestroyed();\n              const keySessionContext = this.createMediaKeySessionContext({\n                decryptdata,\n                keySystem,\n                mediaKeys,\n              });\n              return this.generateRequestWithPreferredKeySession(\n                keySessionContext,\n                initDataType,\n                initData,\n                'encrypted-event-no-match',\n              );\n            });\n          },\n        );\n    }\n    keySessionContextPromise.catch((error) => this.handleError(error));\n  }\n\n  private _onWaitingForKey(event: Event) {\n    this.log(`\"${event.type}\" event`);\n  }\n\n  private attemptSetMediaKeys(\n    keySystem: KeySystems,\n    mediaKeys: MediaKeys,\n  ): Promise<void> {\n    const queue = this.setMediaKeysQueue.slice();\n\n    this.log(`Setting media-keys for \"${keySystem}\"`);\n    // Only one setMediaKeys() can run at one time, and multiple setMediaKeys() operations\n    // can be queued for execution for multiple key sessions.\n    const setMediaKeysPromise = Promise.all(queue).then(() => {\n      if (!this.media) {\n        throw new Error(\n          'Attempted to set mediaKeys without media element attached',\n        );\n      }\n      return this.media.setMediaKeys(mediaKeys);\n    });\n    this.setMediaKeysQueue.push(setMediaKeysPromise);\n    return setMediaKeysPromise.then(() => {\n      this.log(`Media-keys set for \"${keySystem}\"`);\n      queue.push(setMediaKeysPromise!);\n      this.setMediaKeysQueue = this.setMediaKeysQueue.filter(\n        (p) => queue.indexOf(p) === -1,\n      );\n    });\n  }\n\n  private generateRequestWithPreferredKeySession(\n    context: MediaKeySessionContext,\n    initDataType: string,\n    initData: ArrayBuffer | null,\n    reason:\n      | 'playlist-key'\n      | 'encrypted-event-key-match'\n      | 'encrypted-event-no-match'\n      | 'expired',\n  ): Promise<MediaKeySessionContext> | never {\n    const generateRequestFilter =\n      this.config.drmSystems?.[context.keySystem]?.generateRequest;\n    if (generateRequestFilter) {\n      try {\n        const mappedInitData: ReturnType<typeof generateRequestFilter> =\n          generateRequestFilter.call(this.hls, initDataType, initData, context);\n        if (!mappedInitData) {\n          throw new Error(\n            'Invalid response from configured generateRequest filter',\n          );\n        }\n        initDataType = mappedInitData.initDataType;\n        initData = context.decryptdata.pssh = mappedInitData.initData\n          ? new Uint8Array(mappedInitData.initData)\n          : null;\n      } catch (error) {\n        this.warn(error.message);\n        if (this.hls?.config.debug) {\n          throw error;\n        }\n      }\n    }\n\n    if (initData === null) {\n      this.log(`Skipping key-session request for \"${reason}\" (no initData)`);\n      return Promise.resolve(context);\n    }\n\n    const keyId = this.getKeyIdString(context.decryptdata);\n    this.log(\n      `Generating key-session request for \"${reason}\": ${keyId} (init data type: ${initDataType} length: ${\n        initData ? initData.byteLength : null\n      })`,\n    );\n\n    const licenseStatus = new EventEmitter();\n\n    const onmessage = (context._onmessage = (event: MediaKeyMessageEvent) => {\n      const keySession = context.mediaKeysSession;\n      if (!keySession) {\n        licenseStatus.emit('error', new Error('invalid state'));\n        return;\n      }\n      const { messageType, message } = event;\n      this.log(\n        `\"${messageType}\" message event for session \"${keySession.sessionId}\" message size: ${message.byteLength}`,\n      );\n      if (\n        messageType === 'license-request' ||\n        messageType === 'license-renewal'\n      ) {\n        this.renewLicense(context, message).catch((error) => {\n          this.handleError(error);\n          licenseStatus.emit('error', error);\n        });\n      } else if (messageType === 'license-release') {\n        if (context.keySystem === KeySystems.FAIRPLAY) {\n          this.updateKeySession(context, strToUtf8array('acknowledged'));\n          this.removeSession(context);\n        }\n      } else {\n        this.warn(`unhandled media key message type \"${messageType}\"`);\n      }\n    });\n\n    const onkeystatuseschange = (context._onkeystatuseschange = (\n      event: Event,\n    ) => {\n      const keySession = context.mediaKeysSession;\n      if (!keySession) {\n        licenseStatus.emit('error', new Error('invalid state'));\n        return;\n      }\n      this.onKeyStatusChange(context);\n      const keyStatus = context.keyStatus;\n      licenseStatus.emit('keyStatus', keyStatus);\n      if (keyStatus === 'expired') {\n        this.warn(`${context.keySystem} expired for key ${keyId}`);\n        this.renewKeySession(context);\n      }\n    });\n\n    context.mediaKeysSession.addEventListener('message', onmessage);\n    context.mediaKeysSession.addEventListener(\n      'keystatuseschange',\n      onkeystatuseschange,\n    );\n\n    const keyUsablePromise = new Promise(\n      (resolve: (value?: void) => void, reject) => {\n        licenseStatus.on('error', reject);\n\n        licenseStatus.on('keyStatus', (keyStatus) => {\n          if (keyStatus.startsWith('usable')) {\n            resolve();\n          } else if (keyStatus === 'output-restricted') {\n            reject(\n              new EMEKeyError(\n                {\n                  type: ErrorTypes.KEY_SYSTEM_ERROR,\n                  details: ErrorDetails.KEY_SYSTEM_STATUS_OUTPUT_RESTRICTED,\n                  fatal: false,\n                },\n                'HDCP level output restricted',\n              ),\n            );\n          } else if (keyStatus === 'internal-error') {\n            reject(\n              new EMEKeyError(\n                {\n                  type: ErrorTypes.KEY_SYSTEM_ERROR,\n                  details: ErrorDetails.KEY_SYSTEM_STATUS_INTERNAL_ERROR,\n                  fatal: true,\n                },\n                `key status changed to \"${keyStatus}\"`,\n              ),\n            );\n          } else if (keyStatus === 'expired') {\n            reject(new Error('key expired while generating request'));\n          } else {\n            this.warn(`unhandled key status change \"${keyStatus}\"`);\n          }\n        });\n      },\n    );\n\n    return context.mediaKeysSession\n      .generateRequest(initDataType, initData)\n      .then(() => {\n        this.log(\n          `Request generated for key-session \"${context.mediaKeysSession?.sessionId}\" keyId: ${keyId}`,\n        );\n      })\n      .catch((error) => {\n        throw new EMEKeyError(\n          {\n            type: ErrorTypes.KEY_SYSTEM_ERROR,\n            details: ErrorDetails.KEY_SYSTEM_NO_SESSION,\n            error,\n            fatal: false,\n          },\n          `Error generating key-session request: ${error}`,\n        );\n      })\n      .then(() => keyUsablePromise)\n      .catch((error) => {\n        licenseStatus.removeAllListeners();\n        this.removeSession(context);\n        throw error;\n      })\n      .then(() => {\n        licenseStatus.removeAllListeners();\n        return context;\n      });\n  }\n\n  private onKeyStatusChange(mediaKeySessionContext: MediaKeySessionContext) {\n    mediaKeySessionContext.mediaKeysSession.keyStatuses.forEach(\n      (status: MediaKeyStatus, keyId: BufferSource) => {\n        this.log(\n          `key status change \"${status}\" for keyStatuses keyId: ${Hex.hexDump(\n            'buffer' in keyId\n              ? new Uint8Array(keyId.buffer, keyId.byteOffset, keyId.byteLength)\n              : new Uint8Array(keyId),\n          )} session keyId: ${Hex.hexDump(\n            new Uint8Array(mediaKeySessionContext.decryptdata.keyId || []),\n          )} uri: ${mediaKeySessionContext.decryptdata.uri}`,\n        );\n        mediaKeySessionContext.keyStatus = status;\n      },\n    );\n  }\n\n  private fetchServerCertificate(\n    keySystem: KeySystems,\n  ): Promise<BufferSource | void> {\n    const config = this.config;\n    const Loader = config.loader;\n    const certLoader = new Loader(config as HlsConfig) as Loader<LoaderContext>;\n    const url = this.getServerCertificateUrl(keySystem);\n    if (!url) {\n      return Promise.resolve();\n    }\n    this.log(`Fetching server certificate for \"${keySystem}\"`);\n    return new Promise((resolve, reject) => {\n      const loaderContext: LoaderContext = {\n        responseType: 'arraybuffer',\n        url,\n      };\n      const loadPolicy = config.certLoadPolicy.default;\n      const loaderConfig: LoaderConfiguration = {\n        loadPolicy,\n        timeout: loadPolicy.maxLoadTimeMs,\n        maxRetry: 0,\n        retryDelay: 0,\n        maxRetryDelay: 0,\n      };\n      const loaderCallbacks: LoaderCallbacks<LoaderContext> = {\n        onSuccess: (response, stats, context, networkDetails) => {\n          resolve(response.data as ArrayBuffer);\n        },\n        onError: (response, contex, networkDetails, stats) => {\n          reject(\n            new EMEKeyError(\n              {\n                type: ErrorTypes.KEY_SYSTEM_ERROR,\n                details:\n                  ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED,\n                fatal: true,\n                networkDetails,\n                response: {\n                  url: loaderContext.url,\n                  data: undefined,\n                  ...response,\n                },\n              },\n              `\"${keySystem}\" certificate request failed (${url}). Status: ${response.code} (${response.text})`,\n            ),\n          );\n        },\n        onTimeout: (stats, context, networkDetails) => {\n          reject(\n            new EMEKeyError(\n              {\n                type: ErrorTypes.KEY_SYSTEM_ERROR,\n                details:\n                  ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED,\n                fatal: true,\n                networkDetails,\n                response: {\n                  url: loaderContext.url,\n                  data: undefined,\n                },\n              },\n              `\"${keySystem}\" certificate request timed out (${url})`,\n            ),\n          );\n        },\n        onAbort: (stats, context, networkDetails) => {\n          reject(new Error('aborted'));\n        },\n      };\n      certLoader.load(loaderContext, loaderConfig, loaderCallbacks);\n    });\n  }\n\n  private setMediaKeysServerCertificate(\n    mediaKeys: MediaKeys,\n    keySystem: KeySystems,\n    cert: BufferSource,\n  ): Promise<MediaKeys> {\n    return new Promise((resolve, reject) => {\n      mediaKeys\n        .setServerCertificate(cert)\n        .then((success) => {\n          this.log(\n            `setServerCertificate ${\n              success ? 'success' : 'not supported by CDM'\n            } (${cert?.byteLength}) on \"${keySystem}\"`,\n          );\n          resolve(mediaKeys);\n        })\n        .catch((error) => {\n          reject(\n            new EMEKeyError(\n              {\n                type: ErrorTypes.KEY_SYSTEM_ERROR,\n                details:\n                  ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_UPDATE_FAILED,\n                error,\n                fatal: true,\n              },\n              error.message,\n            ),\n          );\n        });\n    });\n  }\n\n  private renewLicense(\n    context: MediaKeySessionContext,\n    keyMessage: ArrayBuffer,\n  ): Promise<void> {\n    return this.requestLicense(context, new Uint8Array(keyMessage)).then(\n      (data: ArrayBuffer) => {\n        return this.updateKeySession(context, new Uint8Array(data)).catch(\n          (error) => {\n            throw new EMEKeyError(\n              {\n                type: ErrorTypes.KEY_SYSTEM_ERROR,\n                details: ErrorDetails.KEY_SYSTEM_SESSION_UPDATE_FAILED,\n                error,\n                fatal: true,\n              },\n              error.message,\n            );\n          },\n        );\n      },\n    );\n  }\n\n  private unpackPlayReadyKeyMessage(\n    xhr: XMLHttpRequest,\n    licenseChallenge: Uint8Array,\n  ): Uint8Array {\n    // On Edge, the raw license message is UTF-16-encoded XML.  We need\n    // to unpack the Challenge element (base64-encoded string containing the\n    // actual license request) and any HttpHeader elements (sent as request\n    // headers).\n    // For PlayReady CDMs, we need to dig the Challenge out of the XML.\n    const xmlString = String.fromCharCode.apply(\n      null,\n      new Uint16Array(licenseChallenge.buffer),\n    );\n    if (!xmlString.includes('PlayReadyKeyMessage')) {\n      // This does not appear to be a wrapped message as on Edge.  Some\n      // clients do not need this unwrapping, so we will assume this is one of\n      // them.  Note that \"xml\" at this point probably looks like random\n      // garbage, since we interpreted UTF-8 as UTF-16.\n      xhr.setRequestHeader('Content-Type', 'text/xml; charset=utf-8');\n      return licenseChallenge;\n    }\n    const keyMessageXml = new DOMParser().parseFromString(\n      xmlString,\n      'application/xml',\n    );\n    // Set request headers.\n    const headers = keyMessageXml.querySelectorAll('HttpHeader');\n    if (headers.length > 0) {\n      let header: Element;\n      for (let i = 0, len = headers.length; i < len; i++) {\n        header = headers[i];\n        const name = header.querySelector('name')?.textContent;\n        const value = header.querySelector('value')?.textContent;\n        if (name && value) {\n          xhr.setRequestHeader(name, value);\n        }\n      }\n    }\n    const challengeElement = keyMessageXml.querySelector('Challenge');\n    const challengeText = challengeElement?.textContent;\n    if (!challengeText) {\n      throw new Error(`Cannot find <Challenge> in key message`);\n    }\n    return strToUtf8array(atob(challengeText));\n  }\n\n  private setupLicenseXHR(\n    xhr: XMLHttpRequest,\n    url: string,\n    keysListItem: MediaKeySessionContext,\n    licenseChallenge: Uint8Array,\n  ): Promise<{ xhr: XMLHttpRequest; licenseChallenge: Uint8Array }> {\n    const licenseXhrSetup = this.config.licenseXhrSetup;\n\n    if (!licenseXhrSetup) {\n      xhr.open('POST', url, true);\n\n      return Promise.resolve({ xhr, licenseChallenge });\n    }\n\n    return Promise.resolve()\n      .then(() => {\n        if (!keysListItem.decryptdata) {\n          throw new Error('Key removed');\n        }\n        return licenseXhrSetup.call(\n          this.hls,\n          xhr,\n          url,\n          keysListItem,\n          licenseChallenge,\n        );\n      })\n      .catch((error: Error) => {\n        if (!keysListItem.decryptdata) {\n          // Key session removed. Cancel license request.\n          throw error;\n        }\n        // let's try to open before running setup\n        xhr.open('POST', url, true);\n\n        return licenseXhrSetup.call(\n          this.hls,\n          xhr,\n          url,\n          keysListItem,\n          licenseChallenge,\n        );\n      })\n      .then((licenseXhrSetupResult) => {\n        // if licenseXhrSetup did not yet call open, let's do it now\n        if (!xhr.readyState) {\n          xhr.open('POST', url, true);\n        }\n        const finalLicenseChallenge = licenseXhrSetupResult\n          ? licenseXhrSetupResult\n          : licenseChallenge;\n        return { xhr, licenseChallenge: finalLicenseChallenge };\n      });\n  }\n\n  private requestLicense(\n    keySessionContext: MediaKeySessionContext,\n    licenseChallenge: Uint8Array,\n  ): Promise<ArrayBuffer> {\n    const keyLoadPolicy = this.config.keyLoadPolicy.default;\n    return new Promise((resolve, reject) => {\n      const url = this.getLicenseServerUrl(keySessionContext.keySystem);\n      this.log(`Sending license request to URL: ${url}`);\n      const xhr = new XMLHttpRequest();\n      xhr.responseType = 'arraybuffer';\n      xhr.onreadystatechange = () => {\n        if (!this.hls || !keySessionContext.mediaKeysSession) {\n          return reject(new Error('invalid state'));\n        }\n        if (xhr.readyState === 4) {\n          if (xhr.status === 200) {\n            this._requestLicenseFailureCount = 0;\n            let data = xhr.response;\n            this.log(\n              `License received ${\n                data instanceof ArrayBuffer ? data.byteLength : data\n              }`,\n            );\n            const licenseResponseCallback = this.config.licenseResponseCallback;\n            if (licenseResponseCallback) {\n              try {\n                data = licenseResponseCallback.call(\n                  this.hls,\n                  xhr,\n                  url,\n                  keySessionContext,\n                );\n              } catch (error) {\n                this.error(error);\n              }\n            }\n            resolve(data);\n          } else {\n            const retryConfig = keyLoadPolicy.errorRetry;\n            const maxNumRetry = retryConfig ? retryConfig.maxNumRetry : 0;\n            this._requestLicenseFailureCount++;\n            if (\n              this._requestLicenseFailureCount > maxNumRetry ||\n              (xhr.status >= 400 && xhr.status < 500)\n            ) {\n              reject(\n                new EMEKeyError(\n                  {\n                    type: ErrorTypes.KEY_SYSTEM_ERROR,\n                    details: ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED,\n                    fatal: true,\n                    networkDetails: xhr,\n                    response: {\n                      url,\n                      data: undefined as any,\n                      code: xhr.status,\n                      text: xhr.statusText,\n                    },\n                  },\n                  `License Request XHR failed (${url}). Status: ${xhr.status} (${xhr.statusText})`,\n                ),\n              );\n            } else {\n              const attemptsLeft =\n                maxNumRetry - this._requestLicenseFailureCount + 1;\n              this.warn(\n                `Retrying license request, ${attemptsLeft} attempts left`,\n              );\n              this.requestLicense(keySessionContext, licenseChallenge).then(\n                resolve,\n                reject,\n              );\n            }\n          }\n        }\n      };\n      if (\n        keySessionContext.licenseXhr &&\n        keySessionContext.licenseXhr.readyState !== XMLHttpRequest.DONE\n      ) {\n        keySessionContext.licenseXhr.abort();\n      }\n      keySessionContext.licenseXhr = xhr;\n\n      this.setupLicenseXHR(xhr, url, keySessionContext, licenseChallenge).then(\n        ({ xhr, licenseChallenge }) => {\n          if (keySessionContext.keySystem == KeySystems.PLAYREADY) {\n            licenseChallenge = this.unpackPlayReadyKeyMessage(\n              xhr,\n              licenseChallenge,\n            );\n          }\n          xhr.send(licenseChallenge);\n        },\n      );\n    });\n  }\n\n  private onMediaAttached(\n    event: Events.MEDIA_ATTACHED,\n    data: MediaAttachedData,\n  ) {\n    if (!this.config.emeEnabled) {\n      return;\n    }\n\n    const media = data.media;\n\n    // keep reference of media\n    this.media = media;\n\n    media.addEventListener('encrypted', this.onMediaEncrypted);\n    media.addEventListener('waitingforkey', this.onWaitingForKey);\n  }\n\n  private onMediaDetached() {\n    const media = this.media;\n    const mediaKeysList = this.mediaKeySessions;\n    if (media) {\n      media.removeEventListener('encrypted', this.onMediaEncrypted);\n      media.removeEventListener('waitingforkey', this.onWaitingForKey);\n      this.media = null;\n    }\n\n    this._requestLicenseFailureCount = 0;\n    this.setMediaKeysQueue = [];\n    this.mediaKeySessions = [];\n    this.keyIdToKeySessionPromise = {};\n    LevelKey.clearKeyUriToKeyIdMap();\n\n    // Close all sessions and remove media keys from the video element.\n    const keySessionCount = mediaKeysList.length;\n    EMEController.CDMCleanupPromise = Promise.all(\n      mediaKeysList\n        .map((mediaKeySessionContext) =>\n          this.removeSession(mediaKeySessionContext),\n        )\n        .concat(\n          media?.setMediaKeys(null).catch((error) => {\n            this.log(`Could not clear media keys: ${error}`);\n          }),\n        ),\n    )\n      .then(() => {\n        if (keySessionCount) {\n          this.log('finished closing key sessions and clearing media keys');\n          mediaKeysList.length = 0;\n        }\n      })\n      .catch((error) => {\n        this.log(`Could not close sessions and clear media keys: ${error}`);\n      });\n  }\n\n  private onManifestLoading() {\n    this.keyFormatPromise = null;\n  }\n\n  private onManifestLoaded(\n    event: Events.MANIFEST_LOADED,\n    { sessionKeys }: ManifestLoadedData,\n  ) {\n    if (!sessionKeys || !this.config.emeEnabled) {\n      return;\n    }\n    if (!this.keyFormatPromise) {\n      const keyFormats: KeySystemFormats[] = sessionKeys.reduce(\n        (formats: KeySystemFormats[], sessionKey: LevelKey) => {\n          if (\n            formats.indexOf(sessionKey.keyFormat as KeySystemFormats) === -1\n          ) {\n            formats.push(sessionKey.keyFormat as KeySystemFormats);\n          }\n          return formats;\n        },\n        [],\n      );\n      this.log(\n        `Selecting key-system from session-keys ${keyFormats.join(', ')}`,\n      );\n      this.keyFormatPromise = this.getKeyFormatPromise(keyFormats);\n    }\n  }\n\n  private removeSession(\n    mediaKeySessionContext: MediaKeySessionContext,\n  ): Promise<void> | void {\n    const { mediaKeysSession, licenseXhr } = mediaKeySessionContext;\n    if (mediaKeysSession) {\n      this.log(\n        `Remove licenses and keys and close session ${mediaKeysSession.sessionId}`,\n      );\n      if (mediaKeySessionContext._onmessage) {\n        mediaKeysSession.removeEventListener(\n          'message',\n          mediaKeySessionContext._onmessage,\n        );\n        mediaKeySessionContext._onmessage = undefined;\n      }\n      if (mediaKeySessionContext._onkeystatuseschange) {\n        mediaKeysSession.removeEventListener(\n          'keystatuseschange',\n          mediaKeySessionContext._onkeystatuseschange,\n        );\n        mediaKeySessionContext._onkeystatuseschange = undefined;\n      }\n\n      if (licenseXhr && licenseXhr.readyState !== XMLHttpRequest.DONE) {\n        licenseXhr.abort();\n      }\n      mediaKeySessionContext.mediaKeysSession =\n        mediaKeySessionContext.decryptdata =\n        mediaKeySessionContext.licenseXhr =\n          undefined!;\n      const index = this.mediaKeySessions.indexOf(mediaKeySessionContext);\n      if (index > -1) {\n        this.mediaKeySessions.splice(index, 1);\n      }\n      return mediaKeysSession\n        .remove()\n        .catch((error) => {\n          this.log(`Could not remove session: ${error}`);\n        })\n        .then(() => {\n          return mediaKeysSession.close();\n        })\n        .catch((error) => {\n          this.log(`Could not close session: ${error}`);\n        });\n    }\n  }\n}\n\nclass EMEKeyError extends Error {\n  public readonly data: ErrorData;\n  constructor(\n    data: Omit<ErrorData, 'error'> & { error?: Error },\n    message: string,\n  ) {\n    super(message);\n    data.error ||= new Error(message);\n    this.data = data as ErrorData;\n    data.err = data.error;\n  }\n}\n\nexport default EMEController;\n", "/**\n * Common Media Object Type\n *\n * @group CMCD\n * @group CMSD\n *\n * @beta\n */\nexport var CmObjectType;\n(function (CmObjectType) {\n    /**\n     * text file, such as a manifest or playlist\n     */\n    CmObjectType[\"MANIFEST\"] = \"m\";\n    /**\n     * audio only\n     */\n    CmObjectType[\"AUDIO\"] = \"a\";\n    /**\n     * video only\n     */\n    CmObjectType[\"VIDEO\"] = \"v\";\n    /**\n     * muxed audio and video\n     */\n    CmObjectType[\"MUXED\"] = \"av\";\n    /**\n     * init segment\n     */\n    CmObjectType[\"INIT\"] = \"i\";\n    /**\n     * caption or subtitle\n     */\n    CmObjectType[\"CAPTION\"] = \"c\";\n    /**\n     * ISOBMFF timed text track\n     */\n    CmObjectType[\"TIMED_TEXT\"] = \"tt\";\n    /**\n     * cryptographic key, license or certificate.\n     */\n    CmObjectType[\"KEY\"] = \"k\";\n    /**\n     * other\n     */\n    CmObjectType[\"OTHER\"] = \"o\";\n})(CmObjectType || (CmObjectType = {}));\n//# sourceMappingURL=CmObjectType.js.map", "/**\n * Common Media Streaming Format\n *\n * @group CMCD\n * @group CMSD\n *\n * @beta\n */\nexport var CmStreamingFormat;\n(function (CmStreamingFormat) {\n    /**\n     * MPEG DASH\n     */\n    CmStreamingFormat[\"DASH\"] = \"d\";\n    /**\n     * HTTP Live Streaming (HLS)\n     */\n    CmStreamingFormat[\"HLS\"] = \"h\";\n    /**\n     * Smooth Streaming\n     */\n    CmStreamingFormat[\"SMOOTH\"] = \"s\";\n    /**\n     * Other\n     */\n    CmStreamingFormat[\"OTHER\"] = \"o\";\n})(CmStreamingFormat || (CmStreamingFormat = {}));\n//# sourceMappingURL=CmStreamingFormat.js.map", "/**\n * CMCD header fields.\n *\n * @group CMCD\n *\n * @beta\n */\nexport var CmcdHeaderField;\n(function (CmcdHeaderField) {\n    /**\n     * keys whose values vary with the object being requested.\n     */\n    CmcdHeaderField[\"OBJECT\"] = \"CMCD-Object\";\n    /**\n     * keys whose values vary with each request.\n     */\n    CmcdHeaderField[\"REQUEST\"] = \"CMCD-Request\";\n    /**\n     * keys whose values are expected to be invariant over the life of the session.\n     */\n    CmcdHeaderField[\"SESSION\"] = \"CMCD-Session\";\n    /**\n     * keys whose values do not vary with every request or object.\n     */\n    CmcdHeaderField[\"STATUS\"] = \"CMCD-Status\";\n})(CmcdHeaderField || (CmcdHeaderField = {}));\n//# sourceMappingURL=CmcdHeaderField.js.map", "import { CmcdHeaderField } from './CmcdHeaderField.js';\n/**\n * The map of CMCD header fields to official CMCD keys.\n *\n * @internal\n *\n * @group CMCD\n */\nexport const CmcdHeaderMap = {\n    [CmcdHeaderField.OBJECT]: ['br', 'd', 'ot', 'tb'],\n    [CmcdHeaderField.REQUEST]: ['bl', 'dl', 'mtp', 'nor', 'nrr', 'su'],\n    [CmcdHeaderField.SESSION]: ['cid', 'pr', 'sf', 'sid', 'st', 'v'],\n    [CmcdHeaderField.STATUS]: ['bs', 'rtp'],\n};\n//# sourceMappingURL=CmcdHeaderMap.js.map", "/**\n * Structured Field Item\n *\n * @group Structured Field\n *\n * @beta\n */\nexport class SfItem {\n    value;\n    params;\n    constructor(value, params) {\n        if (Array.isArray(value)) {\n            value = value.map((v) => (v instanceof SfItem) ? v : new SfItem(v));\n        }\n        this.value = value;\n        this.params = params;\n    }\n}\n//# sourceMappingURL=SfItem.js.map", "/**\n * A class to represent structured field tokens when `Symbol` is not available.\n *\n * @group Structured Field\n *\n * @beta\n */\nexport class SfToken {\n    description;\n    constructor(description) {\n        this.description = description;\n    }\n}\n//# sourceMappingURL=SfToken.js.map", "export const DICT = 'Dict';\n//# sourceMappingURL=DICT.js.map", "function format(value) {\n    if (Array.isArray(value)) {\n        return JSON.stringify(value);\n    }\n    if (value instanceof Map) {\n        return 'Map{}';\n    }\n    if (value instanceof Set) {\n        return 'Set{}';\n    }\n    if (typeof value === 'object') {\n        return JSON.stringify(value);\n    }\n    return String(value);\n}\nexport function throwError(action, src, type, cause) {\n    return new Error(`failed to ${action} \"${format(src)}\" as ${type}`, { cause });\n}\n//# sourceMappingURL=throwError.js.map", "export const BARE_ITEM = 'Bare Item';\n//# sourceMappingURL=BARE_ITEM.js.map", "export const BOOLEAN = 'Boolean';\n//# sourceMappingURL=BOOLEAN.js.map", "export const BYTES = 'Byte Sequence';\n//# sourceMappingURL=BYTES.js.map", "export const DECIMAL = 'Decimal';\n//# sourceMappingURL=DECIMAL.js.map", "export const INTEGER = 'Integer';\n//# sourceMappingURL=INTEGER.js.map", "export function isInvalidInt(value) {\n    return value < -999999999999999 || 999999999999999 < value;\n}\n//# sourceMappingURL=isInvalidInt.js.map", "export const STRING_REGEX = /[\\x00-\\x1f\\x7f]+/; // eslint-disable-line no-control-regex\n//# sourceMappingURL=STRING_REGEX.js.map", "export const TOKEN = 'Token';\n//# sourceMappingURL=TOKEN.js.map", "export const KEY = 'Key';\n//# sourceMappingURL=KEY.js.map", "import { throwError } from '../utils/throwError.js';\nexport function serializeError(src, type, cause) {\n    return throwError('serialize', src, type, cause);\n}\n//# sourceMappingURL=serializeError.js.map", "import { BOOLEAN } from '../utils/BOOLEAN.js';\nimport { serializeError } from './serializeError.js';\n// 4.1.9.  Serializing a Boolean\n//\n// Given a Boolean as input_boolean, return an ASCII string suitable for\n// use in a HTTP field value.\n//\n// 1.  If input_boolean is not a boolean, fail serialization.\n//\n// 2.  Let output be an empty string.\n//\n// 3.  Append \"?\" to output.\n//\n// 4.  If input_boolean is true, append \"1\" to output.\n//\n// 5.  If input_boolean is false, append \"0\" to output.\n//\n// 6.  Return output.\nexport function serializeBoolean(value) {\n    if (typeof value !== 'boolean') {\n        throw serializeError(value, BOOLEAN);\n    }\n    return value ? '?1' : '?0';\n}\n//# sourceMappingURL=serializeBoolean.js.map", "/**\n * Encodes binary data to base64\n *\n * @param binary - The binary data to encode\n * @returns The base64 encoded string\n *\n * @group Utils\n *\n * @beta\n */\nexport function base64encode(binary) {\n    return btoa(String.fromCharCode(...binary));\n}\n//# sourceMappingURL=base64encode.js.map", "import { base64encode } from '../../utils/base64encode.js';\nimport { BYTES } from '../utils/BYTES.js';\nimport { serializeError } from './serializeError.js';\n// 4.1.8.  Serializing a Byte Sequence\n//\n// Given a Byte Sequence as input_bytes, return an ASCII string suitable\n// for use in a HTTP field value.\n//\n// 1.  If input_bytes is not a sequence of bytes, fail serialization.\n//\n// 2.  Let output be an empty string.\n//\n// 3.  Append \":\" to output.\n//\n// 4.  Append the result of base64-encoding input_bytes as per\n//     [RFC4648], Section 4, taking account of the requirements below.\n//\n// 5.  Append \":\" to output.\n//\n// 6.  Return output.\n//\n// The encoded data is required to be padded with \"=\", as per [RFC4648],\n// Section 3.2.\n//\n// Likewise, encoded data SHOULD have pad bits set to zero, as per\n// [RFC4648], Section 3.5, unless it is not possible to do so due to\n// implementation constraints.\nexport function serializeByteSequence(value) {\n    if (ArrayBuffer.isView(value) === false) {\n        throw serializeError(value, BYTES);\n    }\n    return `:${base64encode(value)}:`;\n}\n//# sourceMappingURL=serializeByteSequence.js.map", "import { INTEGER } from '../utils/INTEGER.js';\nimport { isInvalidInt } from '../utils/isInvalidInt.js';\nimport { serializeError } from './serializeError.js';\n// 4.1.4.  Serializing an Integer\n//\n// Given an Integer as input_integer, return an ASCII string suitable\n// for use in a HTTP field value.\n//\n// 1.  If input_integer is not an integer in the range of\n//     -999,999,999,999,999 to 999,999,999,999,999 inclusive, fail\n//     serialization.\n//\n// 2.  Let output be an empty string.\n//\n// 3.  If input_integer is less than (but not equal to) 0, append \"-\" to\n//     output.\n//\n// 4.  Append input_integer's numeric value represented in base 10 using\n//     only decimal digits to output.\n//\n// 5.  Return output.\nexport function serializeInteger(value) {\n    if (isInvalidInt(value)) {\n        throw serializeError(value, INTEGER);\n    }\n    return value.toString();\n}\n//# sourceMappingURL=serializeInteger.js.map", "import { serializeInteger } from './serializeInteger.js';\n// 4.1.10.  Serializing a Date\n//\n// Given a Date as input_integer, return an ASCII string suitable for\n// use in an HTTP field value.\n// 1.  Let output be \"@\".\n// 2.  Append to output the result of running Serializing an Integer\n//     with input_date (Section 4.1.4).\n// 3.  Return output.\nexport function serializeDate(value) {\n    return `@${serializeInteger(value.getTime() / 1000)}`;\n}\n//# sourceMappingURL=serializeDate.js.map", "/**\n * This implements the rounding procedure described in step 2 of the \"Serializing a Decimal\" specification.\n * This rounding style is known as \"even rounding\", \"banker's rounding\", or \"commercial rounding\".\n *\n * @param value - The value to round\n * @param precision - The number of decimal places to round to\n * @returns The rounded value\n *\n * @group Utils\n *\n * @beta\n */\nexport function roundToEven(value, precision) {\n    if (value < 0) {\n        return -roundToEven(-value, precision);\n    }\n    const decimalShift = Math.pow(10, precision);\n    const isEquidistant = Math.abs(((value * decimalShift) % 1) - 0.5) < Number.EPSILON;\n    if (isEquidistant) {\n        // If the tail of the decimal place is 'equidistant' we round to the nearest even value\n        const flooredValue = Math.floor(value * decimalShift);\n        return (flooredValue % 2 === 0 ? flooredValue : flooredValue + 1) / decimalShift;\n    }\n    else {\n        // Otherwise, proceed as normal\n        return Math.round(value * decimalShift) / decimalShift;\n    }\n}\n//# sourceMappingURL=roundToEven.js.map", "import { roundToEven } from '../../utils/roundToEven.js';\nimport { DECIMAL } from '../utils/DECIMAL.js';\nimport { serializeError } from './serializeError.js';\n// 4.1.5.  Serializing a Decimal\n//\n// Given a decimal number as input_decimal, return an ASCII string\n// suitable for use in a HTTP field value.\n//\n// 1.   If input_decimal is not a decimal number, fail serialization.\n//\n// 2.   If input_decimal has more than three significant digits to the\n//      right of the decimal point, round it to three decimal places,\n//      rounding the final digit to the nearest value, or to the even\n//      value if it is equidistant.\n//\n// 3.   If input_decimal has more than 12 significant digits to the left\n//      of the decimal point after rounding, fail serialization.\n//\n// 4.   Let output be an empty string.\n//\n// 5.   If input_decimal is less than (but not equal to) 0, append \"-\"\n//      to output.\n//\n// 6.   Append input_decimal's integer component represented in base 10\n//      (using only decimal digits) to output; if it is zero, append\n//      \"0\".\n//\n// 7.   Append \".\" to output.\n//\n// 8.   If input_decimal's fractional component is zero, append \"0\" to\n//      output.\n//\n// 9.   Otherwise, append the significant digits of input_decimal's\n//      fractional component represented in base 10 (using only decimal\n//      digits) to output.\n//\n// 10.  Return output.\nexport function serializeDecimal(value) {\n    const roundedValue = roundToEven(value, 3); // round to 3 decimal places\n    if (Math.floor(Math.abs(roundedValue)).toString().length > 12) {\n        throw serializeError(value, DECIMAL);\n    }\n    const stringValue = roundedValue.toString();\n    return stringValue.includes('.') ? stringValue : `${stringValue}.0`;\n}\n//# sourceMappingURL=serializeDecimal.js.map", "export const STRING = 'String';\n//# sourceMappingURL=STRING.js.map", "import { STRING } from '../utils/STRING.js';\nimport { STRING_REGEX } from '../utils/STRING_REGEX.js';\nimport { serializeError } from './serializeError.js';\n// 4.1.6.  Serializing a String\n//\n// Given a String as input_string, return an ASCII string suitable for\n// use in a HTTP field value.\n//\n// 1.  Convert input_string into a sequence of ASCII characters; if\n//     conversion fails, fail serialization.\n//\n// 2.  If input_string contains characters in the range %x00-1f or %x7f\n//     (i.e., not in VCHAR or SP), fail serialization.\n//\n// 3.  Let output be the string DQUOTE.\n//\n// 4.  For each character char in input_string:\n//\n//     1.  If char is \"\\\" or DQUOTE:\n//\n//         1.  Append \"\\\" to output.\n//\n//     2.  Append char to output.\n//\n// 5.  Append DQUOTE to output.\n//\n// 6.  Return output.\nexport function serializeString(value) {\n    if (STRING_REGEX.test(value)) {\n        throw serializeError(value, STRING);\n    }\n    return `\"${value.replace(/\\\\/g, `\\\\\\\\`).replace(/\"/g, `\\\\\"`)}\"`;\n}\n//# sourceMappingURL=serializeString.js.map", "export function symbolToStr(symbol) {\n    return symbol.description || symbol.toString().slice(7, -1);\n}\n//# sourceMappingURL=symbolToStr.js.map", "import { symbolToStr } from '../../cta/utils/symbolToStr.js';\nimport { TOKEN } from '../utils/TOKEN.js';\nimport { serializeError } from './serializeError.js';\nexport function serializeToken(token) {\n    const value = symbolToStr(token);\n    if (/^([a-zA-Z*])([!#$%&'*+\\-.^_`|~\\w:/]*)$/.test(value) === false) {\n        throw serializeError(value, TOKEN);\n    }\n    return value;\n}\n//# sourceMappingURL=serializeToken.js.map", "import { SfToken } from '../SfToken.js';\nimport { BARE_ITEM } from '../utils/BARE_ITEM.js';\nimport { serializeBoolean } from './serializeBoolean.js';\nimport { serializeByteSequence } from './serializeByteSequence.js';\nimport { serializeDate } from './serializeDate.js';\nimport { serializeDecimal } from './serializeDecimal.js';\nimport { serializeError } from './serializeError.js';\nimport { serializeInteger } from './serializeInteger.js';\nimport { serializeString } from './serializeString.js';\nimport { serializeToken } from './serializeToken.js';\n// 4.1.3.1.  Serializing a Bare Item\n//\n// Given an Item as input_item, return an ASCII string suitable for use\n// in a HTTP field value.\n//\n// 1.  If input_item is an Integer, return the result of running\n//     Serializing an Integer (Section 4.1.4) with input_item.\n//\n// 2.  If input_item is a Decimal, return the result of running\n//     Serializing a Decimal (Section 4.1.5) with input_item.\n//\n// 3.  If input_item is a String, return the result of running\n//     Serializing a String (Section 4.1.6) with input_item.\n//\n// 4.  If input_item is a Token, return the result of running\n//     Serializing a Token (Section 4.1.7) with input_item.\n//\n// 5.  If input_item is a Boolean, return the result of running\n//     Serializing a Boolean (Section 4.1.9) with input_item.\n//\n// 6.  If input_item is a Byte Sequence, return the result of running\n//     Serializing a Byte Sequence (Section 4.1.8) with input_item.\n//\n// 7.  If input_item is a Date, return the result of running Serializing\n//     a Date (Section 4.1.10) with input_item.\n//\n// 8.  Otherwise, fail serialization.\nexport function serializeBareItem(value) {\n    switch (typeof value) {\n        case 'number':\n            if (!Number.isFinite(value)) {\n                throw serializeError(value, BARE_ITEM);\n            }\n            if (Number.isInteger(value)) {\n                return serializeInteger(value);\n            }\n            return serializeDecimal(value);\n        case 'string':\n            return serializeString(value);\n        case 'symbol':\n            return serializeToken(value);\n        case 'boolean':\n            return serializeBoolean(value);\n        case 'object':\n            if (value instanceof Date) {\n                return serializeDate(value);\n            }\n            if (value instanceof Uint8Array) {\n                return serializeByteSequence(value);\n            }\n            if (value instanceof SfToken) {\n                return serializeToken(value);\n            }\n        default:\n            // fail\n            throw serializeError(value, BARE_ITEM);\n    }\n}\n//# sourceMappingURL=serializeBareItem.js.map", "import { KEY } from '../utils/KEY.js';\nimport { serializeError } from './serializeError.js';\n// 4.1.1.3.  Serializing a Key\n//\n// Given a key as input_key, return an ASCII string suitable for use in\n// a HTTP field value.\n//\n// 1.  Convert input_key into a sequence of ASCII characters; if\n//     conversion fails, fail serialization.\n//\n// 2.  If input_key contains characters not in lcalpha, DIGIT, \"_\", \"-\",\n//     \".\", or \"*\" fail serialization.\n//\n// 3.  If the first character of input_key is not lcalpha or \"*\", fail\n//     serialization.\n//\n// 4.  Let output be an empty string.\n//\n// 5.  Append input_key to output.\n//\n// 6.  Return output.\nexport function serializeKey(value) {\n    if (/^[a-z*][a-z0-9\\-_.*]*$/.test(value) === false) {\n        throw serializeError(value, KEY);\n    }\n    return value;\n}\n//# sourceMappingURL=serializeKey.js.map", "import { serializeBareItem } from './serializeBareItem.js';\nimport { serializeKey } from './serializeKey.js';\n// 4.1.1.2.  Serializing Parameters\n//\n// Given an ordered Dictionary as input_parameters (each member having a\n// param_name and a param_value), return an ASCII string suitable for\n// use in a HTTP field value.\n//\n// 1.  Let output be an empty string.\n//\n// 2.  For each param_name with a value of param_value in\n//     input_parameters:\n//\n//     1.  Append \";\" to output.\n//\n//     2.  Append the result of running Serializing a Key\n//         (Section 4.1.1.3) with param_name to output.\n//\n//     3.  If param_value is not Boolean true:\n//\n//         1.  Append \"=\" to output.\n//\n//         2.  Append the result of running Serializing a bare Item\n//             (Section 4.1.3.1) with param_value to output.\n//\n// 3.  Return output.\nexport function serializeParams(params) {\n    if (params == null) {\n        return '';\n    }\n    return Object.entries(params)\n        .map(([key, value]) => {\n        if (value === true) {\n            return `;${serializeKey(key)}`; // omit true\n        }\n        return `;${serializeKey(key)}=${serializeBareItem(value)}`;\n    })\n        .join('');\n}\n//# sourceMappingURL=serializeParams.js.map", "import { SfItem } from '../SfItem.js';\nimport { serializeBareItem } from './serializeBareItem.js';\nimport { serializeParams } from './serializeParams.js';\n// 4.1.3.  Serializing an Item\n//\n// Given an Item as bare_item and Parameters as item_parameters, return\n// an ASCII string suitable for use in a HTTP field value.\n//\n// 1.  Let output be an empty string.\n//\n// 2.  Append the result of running Serializing a Bare Item\n//     Section 4.1.3.1 with bare_item to output.\n//\n// 3.  Append the result of running Serializing Parameters\n//     Section 4.1.1.2 with item_parameters to output.\n//\n// 4.  Return output.\nexport function serializeItem(value) {\n    if (value instanceof SfItem) {\n        return `${serializeBareItem(value.value)}${serializeParams(value.params)}`;\n    }\n    else {\n        return serializeBareItem(value);\n    }\n}\n//# sourceMappingURL=serializeItem.js.map", "import { serializeItem } from './serializeItem.js';\nimport { serializeParams } from './serializeParams.js';\n// 4.1.1.1.  Serializing an Inner List\n//\n// Given an array of (member_value, parameters) tuples as inner_list,\n// and parameters as list_parameters, return an ASCII string suitable\n// for use in a HTTP field value.\n//\n// 1.  Let output be the string \"(\".\n//\n// 2.  For each (member_value, parameters) of inner_list:\n//\n//     1.  Append the result of running Serializing an Item\n//         (Section 4.1.3) with (member_value, parameters) to output.\n//\n//     2.  If more values remain in inner_list, append a single SP to\n//         output.\n//\n// 3.  Append \")\" to output.\n//\n// 4.  Append the result of running Serializing Parameters\n//     (Section 4.1.1.2) with list_parameters to output.\n//\n// 5.  Return output.\nexport function serializeInnerList(value) {\n    return `(${value.value.map(serializeItem).join(' ')})${serializeParams(value.params)}`;\n}\n//# sourceMappingURL=serializeInnerList.js.map", "import { SfItem } from '../SfItem.js';\nimport { DICT } from '../utils/DICT.js';\nimport { serializeError } from './serializeError.js';\nimport { serializeInnerList } from './serializeInnerList.js';\nimport { serializeItem } from './serializeItem.js';\nimport { serializeKey } from './serializeKey.js';\nimport { serializeParams } from './serializeParams.js';\n// 4.1.2.  Serializing a Dictionary\n//\n// Given an ordered Dictionary as input_dictionary (each member having a\n// member_name and a tuple value of (member_value, parameters)), return\n// an ASCII string suitable for use in a HTTP field value.\n//\n// 1.  Let output be an empty string.\n//\n// 2.  For each member_name with a value of (member_value, parameters)\n//     in input_dictionary:\n//\n//     1.  Append the result of running Serializing a Key\n//         (Section 4.1.1.3) with member's member_name to output.\n//\n//     2.  If member_value is Boolean true:\n//\n//         1.  Append the result of running Serializing Parameters\n//             (Section 4.1.1.2) with parameters to output.\n//\n//     3.  Otherwise:\n//\n//         1.  Append \"=\" to output.\n//\n//         2.  If member_value is an array, append the result of running\n//             Serializing an Inner List (Section 4.1.1.1) with\n//             (member_value, parameters) to output.\n//\n//         3.  Otherwise, append the result of running Serializing an\n//             Item (Section 4.1.3) with (member_value, parameters) to\n//             output.\n//\n//     4.  If more members remain in input_dictionary:\n//\n//         1.  Append \",\" to output.\n//\n//         2.  Append a single SP to output.\n//\n// 3.  Return output.\nexport function serializeDict(dict, options = { whitespace: true }) {\n    if (typeof dict !== 'object') {\n        throw serializeError(dict, DICT);\n    }\n    const entries = dict instanceof Map ? dict.entries() : Object.entries(dict);\n    const optionalWhiteSpace = options?.whitespace ? ' ' : '';\n    return Array.from(entries)\n        .map(([key, item]) => {\n        if (item instanceof SfItem === false) {\n            item = new SfItem(item);\n        }\n        let output = serializeKey(key);\n        if (item.value === true) {\n            output += serializeParams(item.params);\n        }\n        else {\n            output += '=';\n            if (Array.isArray(item.value)) {\n                output += serializeInnerList(item);\n            }\n            else {\n                output += serializeItem(item);\n            }\n        }\n        return output;\n    })\n        .join(`,${optionalWhiteSpace}`);\n}\n//# sourceMappingURL=serializeDict.js.map", "import { serializeDict } from './serialize/serializeDict.js';\n/**\n * Encode an object into a structured field dictionary\n *\n * @param input - The structured field dictionary to encode\n * @returns The structured field string\n *\n * @group Structured Field\n *\n * @beta\n */\nexport function encodeSfDict(value, options) {\n    return serializeDict(value, options);\n}\n//# sourceMappingURL=encodeSfDict.js.map", "/**\n * Checks if the given key is a token field.\n *\n * @param key - The key to check.\n *\n * @returns `true` if the key is a token field.\n *\n * @internal\n *\n * @group CMCD\n */\nexport const isTokenField = (key) => key === 'ot' || key === 'sf' || key === 'st';\n//# sourceMappingURL=isTokenField.js.map", "export const isValid = (value) => {\n    if (typeof value === 'number') {\n        return Number.isFinite(value);\n    }\n    return value != null && value !== '' && value !== false;\n};\n//# sourceMappingURL=isValid.js.map", "/**\n * Constructs a relative path from a URL.\n *\n * @param url - The destination URL\n * @param base - The base URL\n * @returns The relative path\n *\n * @group Utils\n *\n * @beta\n */\nexport function urlToRelativePath(url, base) {\n    const to = new URL(url);\n    const from = new URL(base);\n    if (to.origin !== from.origin) {\n        return url;\n    }\n    const toPath = to.pathname.split('/').slice(1);\n    const fromPath = from.pathname.split('/').slice(1, -1);\n    // remove common parents\n    while (toPath[0] === fromPath[0]) {\n        toPath.shift();\n        fromPath.shift();\n    }\n    // add back paths\n    while (fromPath.length) {\n        fromPath.shift();\n        toPath.unshift('..');\n    }\n    return toPath.join('/');\n}\n//# sourceMappingURL=urlToRelativePath.js.map", "/**\n * Generate a random v4 UUID\n *\n * @returns A random v4 UUID\n *\n * @group Utils\n *\n * @beta\n */\nexport function uuid() {\n    try {\n        return crypto.randomUUID();\n    }\n    catch (error) {\n        try {\n            const url = URL.createObjectURL(new Blob());\n            const uuid = url.toString();\n            URL.revokeObjectURL(url);\n            return uuid.slice(uuid.lastIndexOf('/') + 1);\n        }\n        catch (error) {\n            let dt = new Date().getTime();\n            const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n                const r = (dt + Math.random() * 16) % 16 | 0;\n                dt = Math.floor(dt / 16);\n                return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16);\n            });\n            return uuid;\n        }\n    }\n}\n//# sourceMappingURL=uuid.js.map", "import { urlToRelativePath } from '../utils.js';\nconst toRounded = (value) => Math.round(value);\nconst toUrlSafe = (value, options) => {\n    if (options?.baseUrl) {\n        value = urlToRelativePath(value, options.baseUrl);\n    }\n    return encodeURIComponent(value);\n};\nconst toHundred = (value) => toRounded(value / 100) * 100;\n/**\n * The default formatters for CMCD values.\n *\n * @group CMCD\n *\n * @beta\n */\nexport const CmcdFormatters = {\n    /**\n     * Bitrate (kbps) rounded integer\n     */\n    br: toRounded,\n    /**\n     * Duration (milliseconds) rounded integer\n     */\n    d: toRounded,\n    /**\n     * Buffer Length (milliseconds) rounded nearest 100ms\n     */\n    bl: toHundred,\n    /**\n     * Deadline (milliseconds) rounded nearest 100ms\n     */\n    dl: toHundred,\n    /**\n     * Measured Throughput (kbps) rounded nearest 100kbps\n     */\n    mtp: toHundred,\n    /**\n     * Next Object Request URL encoded\n     */\n    nor: toUrlSafe,\n    /**\n     * Requested maximum throughput (kbps) rounded nearest 100kbps\n     */\n    rtp: toHundred,\n    /**\n     * Top Bitrate (kbps) rounded integer\n     */\n    tb: toRounded,\n};\n//# sourceMappingURL=CmcdFormatters.js.map", "import { isTokenField } from '../../cta/utils/isTokenField.js';\nimport { isValid } from '../../cta/utils/isValid.js';\nimport { SfToken } from '../../structuredfield/SfToken.js';\nimport { CmcdFormatters } from '../CmcdFormatters.js';\n/**\n * Internal CMCD processing function.\n *\n * @param obj - The CMCD object to process.\n * @param map - The mapping function to use.\n * @param options - Options for encoding.\n *\n * @internal\n *\n * @group CMCD\n */\nexport function processCmcd(obj, options) {\n    const results = {};\n    if (obj == null || typeof obj !== 'object') {\n        return results;\n    }\n    const keys = Object.keys(obj).sort();\n    const formatters = Object.assign({}, CmcdFormatters, options?.formatters);\n    const filter = options?.filter;\n    keys.forEach(key => {\n        if (filter?.(key)) {\n            return;\n        }\n        let value = obj[key];\n        const formatter = formatters[key];\n        if (formatter) {\n            value = formatter(value, options);\n        }\n        // Version should only be reported if not equal to 1.\n        if (key === 'v' && value === 1) {\n            return;\n        }\n        // Playback rate should only be sent if not equal to 1.\n        if (key == 'pr' && value === 1) {\n            return;\n        }\n        // ignore invalid values\n        if (!isValid(value)) {\n            return;\n        }\n        if (isTokenField(key) && typeof value === 'string') {\n            value = new SfToken(value);\n        }\n        results[key] = value;\n    });\n    return results;\n}\n//# sourceMappingURL=processCmcd.js.map", "import { encodeSfDict } from '../structuredfield.js';\nimport { processCmcd } from './utils/processCmcd.js';\n/**\n * Encode a CMCD object to a string.\n *\n * @param cmcd - The CMCD object to encode.\n * @param options - Options for encoding.\n *\n * @returns The encoded CMCD string.\n *\n * @group CMCD\n *\n * @beta\n */\nexport function encodeCmcd(cmcd, options = {}) {\n    if (!cmcd) {\n        return '';\n    }\n    return encodeSfDict(processCmcd(cmcd, options), Object.assign({ whitespace: false }, options));\n}\n//# sourceMappingURL=encodeCmcd.js.map", "import { CmcdHeaderField } from './CmcdHeaderField.js';\nimport { CmcdHeaderMap } from './CmcdHeaderMap.js';\nimport { encodeCmcd } from './encodeCmcd.js';\n/**\n * Convert a CMCD data object to request headers\n *\n * @param cmcd - The CMCD data object to convert.\n * @param options - Options for encoding the CMCD object.\n *\n * @returns The CMCD header shards.\n *\n * @group CMCD\n *\n * @beta\n */\nexport function toCmcdHeaders(cmcd, options = {}) {\n    if (!cmcd) {\n        return {};\n    }\n    const entries = Object.entries(cmcd);\n    const headerMap = Object.entries(CmcdHeaderMap)\n        .concat(Object.entries(options?.customHeaderMap || {}));\n    const shards = entries.reduce((acc, entry) => {\n        const [key, value] = entry;\n        const field = headerMap.find(entry => entry[1].includes(key))?.[0] || CmcdHeaderField.REQUEST;\n        acc[field] ??= {};\n        acc[field][key] = value;\n        return acc;\n    }, {});\n    return Object.entries(shards)\n        .reduce((acc, [field, value]) => {\n        acc[field] = encodeCmcd(value, options);\n        return acc;\n    }, {});\n}\n//# sourceMappingURL=toCmcdHeaders.js.map", "import { toCmcdHeaders } from './toCmcdHeaders.js';\n/**\n * Append CMCD query args to a header object.\n *\n * @param headers - The headers to append to.\n * @param cmcd - The CMCD object to append.\n * @param customHeaderMap - A map of custom CMCD keys to header fields.\n *\n * @returns The headers with the CMCD header shards appended.\n *\n * @group CMCD\n *\n * @beta\n */\nexport function appendCmcdHeaders(headers, cmcd, options) {\n    return Object.assign(headers, toCmcdHeaders(cmcd, options));\n}\n//# sourceMappingURL=appendCmcdHeaders.js.map", "/**\n * CMCD parameter name.\n *\n * @group CMCD\n *\n * @beta\n */\nexport const CMCD_PARAM = 'CMCD';\n//# sourceMappingURL=CMCD_PARAM.js.map", "import { CMCD_PARAM } from './CMCD_PARAM.js';\nimport { encodeCmcd } from './encodeCmcd.js';\n/**\n * Convert a CMCD data object to a query arg.\n *\n * @param cmcd - The CMCD object to convert.\n * @param options - Options for encoding the CMCD object.\n *\n * @returns The CMCD query arg.\n *\n * @group CMCD\n *\n * @beta\n */\nexport function toCmcdQuery(cmcd, options = {}) {\n    if (!cmcd) {\n        return '';\n    }\n    const params = encodeCmcd(cmcd, options);\n    return `${CMCD_PARAM}=${encodeURIComponent(params)}`;\n}\n//# sourceMappingURL=toCmcdQuery.js.map", "import { toCmcdQuery } from './toCmcdQuery.js';\nconst REGEX = /CMCD=[^&#]+/;\n/**\n * Append CMCD query args to a URL.\n *\n * @param url - The URL to append to.\n * @param cmcd - The CMCD object to append.\n * @param options - Options for encoding the CMCD object.\n *\n * @returns The URL with the CMCD query args appended.\n *\n * @group CMCD\n *\n * @beta\n */\nexport function appendCmcdQuery(url, cmcd, options) {\n    // TODO: Replace with URLSearchParams once we drop Safari < 10.1 & Chrome < 49 support.\n    // https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams\n    const query = toCmcdQuery(cmcd, options);\n    if (!query) {\n        return url;\n    }\n    if (REGEX.test(url)) {\n        return url.replace(REGEX, query);\n    }\n    const separator = url.includes('?') ? '&' : '?';\n    return `${url}${separator}${query}`;\n}\n//# sourceMappingURL=appendCmcdQuery.js.map", "import { Events } from '../events';\nimport Hls from '../hls';\nimport { Cmcd } from '@svta/common-media-library/cmcd/Cmcd';\nimport { CmcdObjectType } from '@svta/common-media-library/cmcd/CmcdObjectType';\nimport { CmcdStreamingFormat } from '@svta/common-media-library/cmcd/CmcdStreamingFormat';\nimport { appendCmcdHeaders } from '@svta/common-media-library/cmcd/appendCmcdHeaders';\nimport { appendCmcdQuery } from '@svta/common-media-library/cmcd/appendCmcdQuery';\nimport { uuid } from '@svta/common-media-library/utils/uuid';\nimport { BufferHelper } from '../utils/buffer-helper';\nimport { logger } from '../utils/logger';\nimport type { ComponentAPI } from '../types/component-api';\nimport type { Fragment } from '../loader/fragment';\nimport type { BufferCreatedData, MediaAttachedData } from '../types/events';\nimport type {\n  FragmentLoaderContext,\n  Loader,\n  LoaderCallbacks,\n  LoaderConfiguration,\n  LoaderContext,\n  PlaylistLoaderContext,\n} from '../types/loader';\nimport type {\n  FragmentLoaderConstructor,\n  HlsConfig,\n  PlaylistLoaderConstructor,\n} from '../config';\n\n/**\n * Controller to deal with Common Media Client Data (CMCD)\n * @see https://cdn.cta.tech/cta/media/media/resources/standards/pdfs/cta-5004-final.pdf\n */\nexport default class CMCDController implements ComponentAPI {\n  private hls: Hls;\n  private config: HlsConfig;\n  private media?: HTMLMediaElement;\n  private sid?: string;\n  private cid?: string;\n  private useHeaders: boolean = false;\n  private includeKeys?: string[];\n  private initialized: boolean = false;\n  private starved: boolean = false;\n  private buffering: boolean = true;\n  private audioBuffer?: SourceBuffer; // eslint-disable-line no-restricted-globals\n  private videoBuffer?: SourceBuffer; // eslint-disable-line no-restricted-globals\n\n  constructor(hls: Hls) {\n    this.hls = hls;\n    const config = (this.config = hls.config);\n    const { cmcd } = config;\n\n    if (cmcd != null) {\n      config.pLoader = this.createPlaylistLoader();\n      config.fLoader = this.createFragmentLoader();\n\n      this.sid = cmcd.sessionId || uuid();\n      this.cid = cmcd.contentId;\n      this.useHeaders = cmcd.useHeaders === true;\n      this.includeKeys = cmcd.includeKeys;\n      this.registerListeners();\n    }\n  }\n\n  private registerListeners() {\n    const hls = this.hls;\n    hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n    hls.on(Events.MEDIA_DETACHED, this.onMediaDetached, this);\n    hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);\n  }\n\n  private unregisterListeners() {\n    const hls = this.hls;\n    hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n    hls.off(Events.MEDIA_DETACHED, this.onMediaDetached, this);\n    hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);\n  }\n\n  destroy() {\n    this.unregisterListeners();\n    this.onMediaDetached();\n\n    // @ts-ignore\n    this.hls = this.config = this.audioBuffer = this.videoBuffer = null;\n    // @ts-ignore\n    this.onWaiting = this.onPlaying = null;\n  }\n\n  private onMediaAttached(\n    event: Events.MEDIA_ATTACHED,\n    data: MediaAttachedData,\n  ) {\n    this.media = data.media;\n    this.media.addEventListener('waiting', this.onWaiting);\n    this.media.addEventListener('playing', this.onPlaying);\n  }\n\n  private onMediaDetached() {\n    if (!this.media) {\n      return;\n    }\n\n    this.media.removeEventListener('waiting', this.onWaiting);\n    this.media.removeEventListener('playing', this.onPlaying);\n\n    // @ts-ignore\n    this.media = null;\n  }\n\n  private onBufferCreated(\n    event: Events.BUFFER_CREATED,\n    data: BufferCreatedData,\n  ) {\n    this.audioBuffer = data.tracks.audio?.buffer;\n    this.videoBuffer = data.tracks.video?.buffer;\n  }\n\n  private onWaiting = () => {\n    if (this.initialized) {\n      this.starved = true;\n    }\n\n    this.buffering = true;\n  };\n\n  private onPlaying = () => {\n    if (!this.initialized) {\n      this.initialized = true;\n    }\n\n    this.buffering = false;\n  };\n\n  /**\n   * Create baseline CMCD data\n   */\n  private createData(): Cmcd {\n    return {\n      v: 1,\n      sf: CmcdStreamingFormat.HLS,\n      sid: this.sid,\n      cid: this.cid,\n      pr: this.media?.playbackRate,\n      mtp: this.hls.bandwidthEstimate / 1000,\n    };\n  }\n\n  /**\n   * Apply CMCD data to a request.\n   */\n  private apply(context: LoaderContext, data: Cmcd = {}) {\n    // apply baseline data\n    Object.assign(data, this.createData());\n\n    const isVideo =\n      data.ot === CmcdObjectType.INIT ||\n      data.ot === CmcdObjectType.VIDEO ||\n      data.ot === CmcdObjectType.MUXED;\n\n    if (this.starved && isVideo) {\n      data.bs = true;\n      data.su = true;\n      this.starved = false;\n    }\n\n    if (data.su == null) {\n      data.su = this.buffering;\n    }\n\n    // TODO: Implement rtp, nrr, nor, dl\n\n    const { includeKeys } = this;\n    if (includeKeys) {\n      data = Object.keys(data).reduce((acc, key) => {\n        includeKeys.includes(key) && (acc[key] = data[key]);\n        return acc;\n      }, {});\n    }\n\n    if (this.useHeaders) {\n      if (!context.headers) {\n        context.headers = {};\n      }\n\n      appendCmcdHeaders(context.headers, data);\n    } else {\n      context.url = appendCmcdQuery(context.url, data);\n    }\n  }\n\n  /**\n   * Apply CMCD data to a manifest request.\n   */\n  private applyPlaylistData = (context: PlaylistLoaderContext) => {\n    try {\n      this.apply(context, {\n        ot: CmcdObjectType.MANIFEST,\n        su: !this.initialized,\n      });\n    } catch (error) {\n      logger.warn('Could not generate manifest CMCD data.', error);\n    }\n  };\n\n  /**\n   * Apply CMCD data to a segment request\n   */\n  private applyFragmentData = (context: FragmentLoaderContext) => {\n    try {\n      const fragment = context.frag;\n      const level = this.hls.levels[fragment.level];\n      const ot = this.getObjectType(fragment);\n      const data: Cmcd = {\n        d: fragment.duration * 1000,\n        ot,\n      };\n\n      if (\n        ot === CmcdObjectType.VIDEO ||\n        ot === CmcdObjectType.AUDIO ||\n        ot == CmcdObjectType.MUXED\n      ) {\n        data.br = level.bitrate / 1000;\n        data.tb = this.getTopBandwidth(ot) / 1000;\n        data.bl = this.getBufferLength(ot);\n      }\n\n      this.apply(context, data);\n    } catch (error) {\n      logger.warn('Could not generate segment CMCD data.', error);\n    }\n  };\n\n  /**\n   * The CMCD object type.\n   */\n  private getObjectType(fragment: Fragment): CmcdObjectType | undefined {\n    const { type } = fragment;\n\n    if (type === 'subtitle') {\n      return CmcdObjectType.TIMED_TEXT;\n    }\n\n    if (fragment.sn === 'initSegment') {\n      return CmcdObjectType.INIT;\n    }\n\n    if (type === 'audio') {\n      return CmcdObjectType.AUDIO;\n    }\n\n    if (type === 'main') {\n      if (!this.hls.audioTracks.length) {\n        return CmcdObjectType.MUXED;\n      }\n\n      return CmcdObjectType.VIDEO;\n    }\n\n    return undefined;\n  }\n\n  /**\n   * Get the highest bitrate.\n   */\n  private getTopBandwidth(type: CmcdObjectType) {\n    let bitrate: number = 0;\n    let levels;\n    const hls = this.hls;\n\n    if (type === CmcdObjectType.AUDIO) {\n      levels = hls.audioTracks;\n    } else {\n      const max = hls.maxAutoLevel;\n      const len = max > -1 ? max + 1 : hls.levels.length;\n      levels = hls.levels.slice(0, len);\n    }\n\n    for (const level of levels) {\n      if (level.bitrate > bitrate) {\n        bitrate = level.bitrate;\n      }\n    }\n\n    return bitrate > 0 ? bitrate : NaN;\n  }\n\n  /**\n   * Get the buffer length for a media type in milliseconds\n   */\n  private getBufferLength(type: CmcdObjectType) {\n    const media = this.hls.media;\n    const buffer =\n      type === CmcdObjectType.AUDIO ? this.audioBuffer : this.videoBuffer;\n\n    if (!buffer || !media) {\n      return NaN;\n    }\n\n    const info = BufferHelper.bufferInfo(\n      buffer,\n      media.currentTime,\n      this.config.maxBufferHole,\n    );\n\n    return info.len * 1000;\n  }\n\n  /**\n   * Create a playlist loader\n   */\n  private createPlaylistLoader(): PlaylistLoaderConstructor | undefined {\n    const { pLoader } = this.config;\n    const apply = this.applyPlaylistData;\n    const Ctor = pLoader || (this.config.loader as PlaylistLoaderConstructor);\n\n    return class CmcdPlaylistLoader {\n      private loader: Loader<PlaylistLoaderContext>;\n\n      constructor(config: HlsConfig) {\n        this.loader = new Ctor(config);\n      }\n\n      get stats() {\n        return this.loader.stats;\n      }\n\n      get context() {\n        return this.loader.context;\n      }\n\n      destroy() {\n        this.loader.destroy();\n      }\n\n      abort() {\n        this.loader.abort();\n      }\n\n      load(\n        context: PlaylistLoaderContext,\n        config: LoaderConfiguration,\n        callbacks: LoaderCallbacks<PlaylistLoaderContext>,\n      ) {\n        apply(context);\n        this.loader.load(context, config, callbacks);\n      }\n    };\n  }\n\n  /**\n   * Create a playlist loader\n   */\n  private createFragmentLoader(): FragmentLoaderConstructor | undefined {\n    const { fLoader } = this.config;\n    const apply = this.applyFragmentData;\n    const Ctor = fLoader || (this.config.loader as FragmentLoaderConstructor);\n\n    return class CmcdFragmentLoader {\n      private loader: Loader<FragmentLoaderContext>;\n\n      constructor(config: HlsConfig) {\n        this.loader = new Ctor(config);\n      }\n\n      get stats() {\n        return this.loader.stats;\n      }\n\n      get context() {\n        return this.loader.context;\n      }\n\n      destroy() {\n        this.loader.destroy();\n      }\n\n      abort() {\n        this.loader.abort();\n      }\n\n      load(\n        context: FragmentLoaderContext,\n        config: LoaderConfiguration,\n        callbacks: LoaderCallbacks<FragmentLoaderContext>,\n      ) {\n        apply(context);\n        this.loader.load(context, config, callbacks);\n      }\n    };\n  }\n}\n", "import { Events } from '../events';\nimport { Level } from '../types/level';\nimport { reassignFragmentLevelIndexes } from '../utils/level-helper';\nimport { AttrList } from '../utils/attr-list';\nimport { ErrorActionFlags, NetworkErrorAction } from './error-controller';\nimport { logger } from '../utils/logger';\nimport {\n  PlaylistContextType,\n  type Loader,\n  type LoaderCallbacks,\n  type LoaderConfiguration,\n  type LoaderContext,\n  type LoaderResponse,\n  type LoaderStats,\n} from '../types/loader';\nimport type Hls from '../hls';\nimport type { NetworkComponentAPI } from '../types/component-api';\nimport type {\n  SteeringManifestLoadedData,\n  ErrorData,\n  ManifestLoadedData,\n  ManifestParsedData,\n} from '../types/events';\nimport type { RetryConfig } from '../config';\n\nimport type { MediaAttributes, MediaPlaylist } from '../types/media-playlist';\n\nexport type SteeringManifest = {\n  VERSION: 1;\n  TTL: number;\n  'RELOAD-URI'?: string;\n  'PATHWAY-PRIORITY': string[];\n  'PATHWAY-CLONES'?: PathwayClone[];\n};\n\nexport type PathwayClone = {\n  'BASE-ID': string;\n  ID: string;\n  'URI-REPLACEMENT': UriReplacement;\n};\n\nexport type UriReplacement = {\n  HOST?: string;\n  PARAMS?: { [queryParameter: string]: string };\n  'PER-VARIANT-URIS'?: { [stableVariantId: string]: string };\n  'PER-RENDITION-URIS'?: { [stableRenditionId: string]: string };\n};\n\nconst PATHWAY_PENALTY_DURATION_MS = 300000;\n\nexport default class ContentSteeringController implements NetworkComponentAPI {\n  private readonly hls: Hls;\n  private log: (msg: any) => void;\n  private loader: Loader<LoaderContext> | null = null;\n  private uri: string | null = null;\n  private pathwayId: string = '.';\n  private pathwayPriority: string[] | null = null;\n  private timeToLoad: number = 300;\n  private reloadTimer: number = -1;\n  private updated: number = 0;\n  private started: boolean = false;\n  private enabled: boolean = true;\n  private levels: Level[] | null = null;\n  private audioTracks: MediaPlaylist[] | null = null;\n  private subtitleTracks: MediaPlaylist[] | null = null;\n  private penalizedPathways: { [pathwayId: string]: number } = {};\n\n  constructor(hls: Hls) {\n    this.hls = hls;\n    this.log = logger.log.bind(logger, `[content-steering]:`);\n    this.registerListeners();\n  }\n\n  private registerListeners() {\n    const hls = this.hls;\n    hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    hls.on(Events.MANIFEST_LOADED, this.onManifestLoaded, this);\n    hls.on(Events.MANIFEST_PARSED, this.onManifestParsed, this);\n    hls.on(Events.ERROR, this.onError, this);\n  }\n\n  private unregisterListeners() {\n    const hls = this.hls;\n    if (!hls) {\n      return;\n    }\n    hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    hls.off(Events.MANIFEST_LOADED, this.onManifestLoaded, this);\n    hls.off(Events.MANIFEST_PARSED, this.onManifestParsed, this);\n    hls.off(Events.ERROR, this.onError, this);\n  }\n\n  startLoad() {\n    this.started = true;\n    this.clearTimeout();\n    if (this.enabled && this.uri) {\n      if (this.updated) {\n        const ttl = this.timeToLoad * 1000 - (performance.now() - this.updated);\n        if (ttl > 0) {\n          this.scheduleRefresh(this.uri, ttl);\n          return;\n        }\n      }\n      this.loadSteeringManifest(this.uri);\n    }\n  }\n\n  stopLoad() {\n    this.started = false;\n    if (this.loader) {\n      this.loader.destroy();\n      this.loader = null;\n    }\n    this.clearTimeout();\n  }\n\n  clearTimeout() {\n    if (this.reloadTimer !== -1) {\n      self.clearTimeout(this.reloadTimer);\n      this.reloadTimer = -1;\n    }\n  }\n\n  destroy() {\n    this.unregisterListeners();\n    this.stopLoad();\n    // @ts-ignore\n    this.hls = null;\n    this.levels = this.audioTracks = this.subtitleTracks = null;\n  }\n\n  removeLevel(levelToRemove: Level) {\n    const levels = this.levels;\n    if (levels) {\n      this.levels = levels.filter((level) => level !== levelToRemove);\n    }\n  }\n\n  private onManifestLoading() {\n    this.stopLoad();\n    this.enabled = true;\n    this.timeToLoad = 300;\n    this.updated = 0;\n    this.uri = null;\n    this.pathwayId = '.';\n    this.levels = this.audioTracks = this.subtitleTracks = null;\n  }\n\n  private onManifestLoaded(\n    event: Events.MANIFEST_LOADED,\n    data: ManifestLoadedData,\n  ) {\n    const { contentSteering } = data;\n    if (contentSteering === null) {\n      return;\n    }\n    this.pathwayId = contentSteering.pathwayId;\n    this.uri = contentSteering.uri;\n    if (this.started) {\n      this.startLoad();\n    }\n  }\n\n  private onManifestParsed(\n    event: Events.MANIFEST_PARSED,\n    data: ManifestParsedData,\n  ) {\n    this.audioTracks = data.audioTracks;\n    this.subtitleTracks = data.subtitleTracks;\n  }\n\n  private onError(event: Events.ERROR, data: ErrorData) {\n    const { errorAction } = data;\n    if (\n      errorAction?.action === NetworkErrorAction.SendAlternateToPenaltyBox &&\n      errorAction.flags === ErrorActionFlags.MoveAllAlternatesMatchingHost\n    ) {\n      const levels = this.levels;\n      let pathwayPriority = this.pathwayPriority;\n      let errorPathway = this.pathwayId;\n      if (data.context) {\n        const { groupId, pathwayId, type } = data.context;\n        if (groupId && levels) {\n          errorPathway = this.getPathwayForGroupId(groupId, type, errorPathway);\n        } else if (pathwayId) {\n          errorPathway = pathwayId;\n        }\n      }\n      if (!(errorPathway in this.penalizedPathways)) {\n        this.penalizedPathways[errorPathway] = performance.now();\n      }\n      if (!pathwayPriority && levels) {\n        // If PATHWAY-PRIORITY was not provided, list pathways for error handling\n        pathwayPriority = levels.reduce((pathways, level) => {\n          if (pathways.indexOf(level.pathwayId) === -1) {\n            pathways.push(level.pathwayId);\n          }\n          return pathways;\n        }, [] as string[]);\n      }\n      if (pathwayPriority && pathwayPriority.length > 1) {\n        this.updatePathwayPriority(pathwayPriority);\n        errorAction.resolved = this.pathwayId !== errorPathway;\n      }\n      if (!errorAction.resolved) {\n        logger.warn(\n          `Could not resolve ${data.details} (\"${\n            data.error.message\n          }\") with content-steering for Pathway: ${errorPathway} levels: ${\n            levels ? levels.length : levels\n          } priorities: ${JSON.stringify(\n            pathwayPriority,\n          )} penalized: ${JSON.stringify(this.penalizedPathways)}`,\n        );\n      }\n    }\n  }\n\n  public filterParsedLevels(levels: Level[]): Level[] {\n    // Filter levels to only include those that are in the initial pathway\n    this.levels = levels;\n    let pathwayLevels = this.getLevelsForPathway(this.pathwayId);\n    if (pathwayLevels.length === 0) {\n      const pathwayId = levels[0].pathwayId;\n      this.log(\n        `No levels found in Pathway ${this.pathwayId}. Setting initial Pathway to \"${pathwayId}\"`,\n      );\n      pathwayLevels = this.getLevelsForPathway(pathwayId);\n      this.pathwayId = pathwayId;\n    }\n    if (pathwayLevels.length !== levels.length) {\n      this.log(\n        `Found ${pathwayLevels.length}/${levels.length} levels in Pathway \"${this.pathwayId}\"`,\n      );\n    }\n    return pathwayLevels;\n  }\n\n  private getLevelsForPathway(pathwayId: string): Level[] {\n    if (this.levels === null) {\n      return [];\n    }\n    return this.levels.filter((level) => pathwayId === level.pathwayId);\n  }\n\n  private updatePathwayPriority(pathwayPriority: string[]) {\n    this.pathwayPriority = pathwayPriority;\n    let levels: Level[] | undefined;\n\n    // Evaluate if we should remove the pathway from the penalized list\n    const penalizedPathways = this.penalizedPathways;\n    const now = performance.now();\n    Object.keys(penalizedPathways).forEach((pathwayId) => {\n      if (now - penalizedPathways[pathwayId] > PATHWAY_PENALTY_DURATION_MS) {\n        delete penalizedPathways[pathwayId];\n      }\n    });\n    for (let i = 0; i < pathwayPriority.length; i++) {\n      const pathwayId = pathwayPriority[i];\n      if (pathwayId in penalizedPathways) {\n        continue;\n      }\n      if (pathwayId === this.pathwayId) {\n        return;\n      }\n      const selectedIndex = this.hls.nextLoadLevel;\n      const selectedLevel: Level = this.hls.levels[selectedIndex];\n      levels = this.getLevelsForPathway(pathwayId);\n      if (levels.length > 0) {\n        this.log(`Setting Pathway to \"${pathwayId}\"`);\n        this.pathwayId = pathwayId;\n        reassignFragmentLevelIndexes(levels);\n        this.hls.trigger(Events.LEVELS_UPDATED, { levels });\n        // Set LevelController's level to trigger LEVEL_SWITCHING which loads playlist if needed\n        const levelAfterChange = this.hls.levels[selectedIndex];\n        if (selectedLevel && levelAfterChange && this.levels) {\n          if (\n            levelAfterChange.attrs['STABLE-VARIANT-ID'] !==\n              selectedLevel.attrs['STABLE-VARIANT-ID'] &&\n            levelAfterChange.bitrate !== selectedLevel.bitrate\n          ) {\n            this.log(\n              `Unstable Pathways change from bitrate ${selectedLevel.bitrate} to ${levelAfterChange.bitrate}`,\n            );\n          }\n          this.hls.nextLoadLevel = selectedIndex;\n        }\n        break;\n      }\n    }\n  }\n\n  private getPathwayForGroupId(\n    groupId: string,\n    type: PlaylistContextType,\n    defaultPathway: string,\n  ): string {\n    const levels = this.getLevelsForPathway(defaultPathway).concat(\n      this.levels || [],\n    );\n    for (let i = 0; i < levels.length; i++) {\n      if (\n        (type === PlaylistContextType.AUDIO_TRACK &&\n          levels[i].hasAudioGroup(groupId)) ||\n        (type === PlaylistContextType.SUBTITLE_TRACK &&\n          levels[i].hasSubtitleGroup(groupId))\n      ) {\n        return levels[i].pathwayId;\n      }\n    }\n    return defaultPathway;\n  }\n\n  private clonePathways(pathwayClones: PathwayClone[]) {\n    const levels = this.levels;\n    if (!levels) {\n      return;\n    }\n    const audioGroupCloneMap: Record<string, string> = {};\n    const subtitleGroupCloneMap: Record<string, string> = {};\n    pathwayClones.forEach((pathwayClone) => {\n      const {\n        ID: cloneId,\n        'BASE-ID': baseId,\n        'URI-REPLACEMENT': uriReplacement,\n      } = pathwayClone;\n      if (levels.some((level) => level.pathwayId === cloneId)) {\n        return;\n      }\n      const clonedVariants = this.getLevelsForPathway(baseId).map(\n        (baseLevel) => {\n          const attributes = new AttrList(baseLevel.attrs);\n          attributes['PATHWAY-ID'] = cloneId;\n          const clonedAudioGroupId: string | undefined =\n            attributes.AUDIO && `${attributes.AUDIO}_clone_${cloneId}`;\n          const clonedSubtitleGroupId: string | undefined =\n            attributes.SUBTITLES && `${attributes.SUBTITLES}_clone_${cloneId}`;\n          if (clonedAudioGroupId) {\n            audioGroupCloneMap[attributes.AUDIO] = clonedAudioGroupId;\n            attributes.AUDIO = clonedAudioGroupId;\n          }\n          if (clonedSubtitleGroupId) {\n            subtitleGroupCloneMap[attributes.SUBTITLES] = clonedSubtitleGroupId;\n            attributes.SUBTITLES = clonedSubtitleGroupId;\n          }\n          const url = performUriReplacement(\n            baseLevel.uri,\n            attributes['STABLE-VARIANT-ID'],\n            'PER-VARIANT-URIS',\n            uriReplacement,\n          );\n          const clonedLevel = new Level({\n            attrs: attributes,\n            audioCodec: baseLevel.audioCodec,\n            bitrate: baseLevel.bitrate,\n            height: baseLevel.height,\n            name: baseLevel.name,\n            url,\n            videoCodec: baseLevel.videoCodec,\n            width: baseLevel.width,\n          });\n          if (baseLevel.audioGroups) {\n            for (let i = 1; i < baseLevel.audioGroups.length; i++) {\n              clonedLevel.addGroupId(\n                'audio',\n                `${baseLevel.audioGroups[i]}_clone_${cloneId}`,\n              );\n            }\n          }\n          if (baseLevel.subtitleGroups) {\n            for (let i = 1; i < baseLevel.subtitleGroups.length; i++) {\n              clonedLevel.addGroupId(\n                'text',\n                `${baseLevel.subtitleGroups[i]}_clone_${cloneId}`,\n              );\n            }\n          }\n          return clonedLevel;\n        },\n      );\n      levels.push(...clonedVariants);\n      cloneRenditionGroups(\n        this.audioTracks,\n        audioGroupCloneMap,\n        uriReplacement,\n        cloneId,\n      );\n      cloneRenditionGroups(\n        this.subtitleTracks,\n        subtitleGroupCloneMap,\n        uriReplacement,\n        cloneId,\n      );\n    });\n  }\n\n  private loadSteeringManifest(uri: string) {\n    const config = this.hls.config;\n    const Loader = config.loader;\n    if (this.loader) {\n      this.loader.destroy();\n    }\n    this.loader = new Loader(config) as Loader<LoaderContext>;\n\n    let url: URL;\n    try {\n      url = new self.URL(uri);\n    } catch (error) {\n      this.enabled = false;\n      this.log(`Failed to parse Steering Manifest URI: ${uri}`);\n      return;\n    }\n    if (url.protocol !== 'data:') {\n      const throughput =\n        (this.hls.bandwidthEstimate || config.abrEwmaDefaultEstimate) | 0;\n      url.searchParams.set('_HLS_pathway', this.pathwayId);\n      url.searchParams.set('_HLS_throughput', '' + throughput);\n    }\n    const context: LoaderContext = {\n      responseType: 'json',\n      url: url.href,\n    };\n\n    const loadPolicy = config.steeringManifestLoadPolicy.default;\n    const legacyRetryCompatibility: RetryConfig | Record<string, void> =\n      loadPolicy.errorRetry || loadPolicy.timeoutRetry || {};\n    const loaderConfig: LoaderConfiguration = {\n      loadPolicy,\n      timeout: loadPolicy.maxLoadTimeMs,\n      maxRetry: legacyRetryCompatibility.maxNumRetry || 0,\n      retryDelay: legacyRetryCompatibility.retryDelayMs || 0,\n      maxRetryDelay: legacyRetryCompatibility.maxRetryDelayMs || 0,\n    };\n\n    const callbacks: LoaderCallbacks<LoaderContext> = {\n      onSuccess: (\n        response: LoaderResponse,\n        stats: LoaderStats,\n        context: LoaderContext,\n        networkDetails: any,\n      ) => {\n        this.log(`Loaded steering manifest: \"${url}\"`);\n        const steeringData = response.data as SteeringManifest;\n        if (steeringData.VERSION !== 1) {\n          this.log(`Steering VERSION ${steeringData.VERSION} not supported!`);\n          return;\n        }\n        this.updated = performance.now();\n        this.timeToLoad = steeringData.TTL;\n        const {\n          'RELOAD-URI': reloadUri,\n          'PATHWAY-CLONES': pathwayClones,\n          'PATHWAY-PRIORITY': pathwayPriority,\n        } = steeringData;\n        if (reloadUri) {\n          try {\n            this.uri = new self.URL(reloadUri, url).href;\n          } catch (error) {\n            this.enabled = false;\n            this.log(\n              `Failed to parse Steering Manifest RELOAD-URI: ${reloadUri}`,\n            );\n            return;\n          }\n        }\n        this.scheduleRefresh(this.uri || context.url);\n        if (pathwayClones) {\n          this.clonePathways(pathwayClones);\n        }\n\n        const loadedSteeringData: SteeringManifestLoadedData = {\n          steeringManifest: steeringData,\n          url: url.toString(),\n        };\n        this.hls.trigger(Events.STEERING_MANIFEST_LOADED, loadedSteeringData);\n\n        if (pathwayPriority) {\n          this.updatePathwayPriority(pathwayPriority);\n        }\n      },\n\n      onError: (\n        error: { code: number; text: string },\n        context: LoaderContext,\n        networkDetails: any,\n        stats: LoaderStats,\n      ) => {\n        this.log(\n          `Error loading steering manifest: ${error.code} ${error.text} (${context.url})`,\n        );\n        this.stopLoad();\n        if (error.code === 410) {\n          this.enabled = false;\n          this.log(`Steering manifest ${context.url} no longer available`);\n          return;\n        }\n        let ttl = this.timeToLoad * 1000;\n        if (error.code === 429) {\n          const loader = this.loader;\n          if (typeof loader?.getResponseHeader === 'function') {\n            const retryAfter = loader.getResponseHeader('Retry-After');\n            if (retryAfter) {\n              ttl = parseFloat(retryAfter) * 1000;\n            }\n          }\n          this.log(`Steering manifest ${context.url} rate limited`);\n          return;\n        }\n        this.scheduleRefresh(this.uri || context.url, ttl);\n      },\n\n      onTimeout: (\n        stats: LoaderStats,\n        context: LoaderContext,\n        networkDetails: any,\n      ) => {\n        this.log(`Timeout loading steering manifest (${context.url})`);\n        this.scheduleRefresh(this.uri || context.url);\n      },\n    };\n\n    this.log(`Requesting steering manifest: ${url}`);\n    this.loader.load(context, loaderConfig, callbacks);\n  }\n\n  private scheduleRefresh(uri: string, ttlMs: number = this.timeToLoad * 1000) {\n    this.clearTimeout();\n    this.reloadTimer = self.setTimeout(() => {\n      const media = this.hls?.media;\n      if (media && !media.ended) {\n        this.loadSteeringManifest(uri);\n        return;\n      }\n      this.scheduleRefresh(uri, this.timeToLoad * 1000);\n    }, ttlMs);\n  }\n}\n\nfunction cloneRenditionGroups(\n  tracks: MediaPlaylist[] | null,\n  groupCloneMap: Record<string, string>,\n  uriReplacement: UriReplacement,\n  cloneId: string,\n) {\n  if (!tracks) {\n    return;\n  }\n  Object.keys(groupCloneMap).forEach((audioGroupId) => {\n    const clonedTracks = tracks\n      .filter((track) => track.groupId === audioGroupId)\n      .map((track) => {\n        const clonedTrack = Object.assign({}, track);\n        clonedTrack.details = undefined;\n        clonedTrack.attrs = new AttrList(clonedTrack.attrs) as MediaAttributes;\n        clonedTrack.url = clonedTrack.attrs.URI = performUriReplacement(\n          track.url,\n          track.attrs['STABLE-RENDITION-ID'],\n          'PER-RENDITION-URIS',\n          uriReplacement,\n        );\n        clonedTrack.groupId = clonedTrack.attrs['GROUP-ID'] =\n          groupCloneMap[audioGroupId];\n        clonedTrack.attrs['PATHWAY-ID'] = cloneId;\n        return clonedTrack;\n      });\n    tracks.push(...clonedTracks);\n  });\n}\n\nfunction performUriReplacement(\n  uri: string,\n  stableId: string | undefined,\n  perOptionKey: 'PER-VARIANT-URIS' | 'PER-RENDITION-URIS',\n  uriReplacement: UriReplacement,\n): string {\n  const {\n    HOST: host,\n    PARAMS: params,\n    [perOptionKey]: perOptionUris,\n  } = uriReplacement;\n  let perVariantUri;\n  if (stableId) {\n    perVariantUri = perOptionUris?.[stableId];\n    if (perVariantUri) {\n      uri = perVariantUri;\n    }\n  }\n  const url = new self.URL(uri);\n  if (host && !perVariantUri) {\n    url.host = host;\n  }\n  if (params) {\n    Object.keys(params)\n      .sort()\n      .forEach((key) => {\n        if (key) {\n          url.searchParams.set(key, params[key]);\n        }\n      });\n  }\n  return url.href;\n}\n", "import { logger } from '../utils/logger';\nimport type {\n  LoaderCallbacks,\n  LoaderContext,\n  LoaderStats,\n  Loader,\n  LoaderConfiguration,\n  LoaderResponse,\n} from '../types/loader';\nimport { LoadStats } from '../loader/load-stats';\nimport { type HlsConfig, RetryConfig } from '../config';\nimport { getRetryDelay, shouldRetry } from './error-helper';\n\nconst AGE_HEADER_LINE_REGEX = /^age:\\s*[\\d.]+\\s*$/im;\n\nclass XhrLoader implements Loader<LoaderContext> {\n  private xhrSetup:\n    | ((xhr: XMLHttpRequest, url: string) => Promise<void> | void)\n    | null;\n  private requestTimeout?: number;\n  private retryTimeout?: number;\n  private retryDelay: number;\n  private config: LoaderConfiguration | null = null;\n  private callbacks: LoaderCallbacks<LoaderContext> | null = null;\n  public context: LoaderContext | null = null;\n\n  private loader: XMLHttpRequest | null = null;\n  public stats: LoaderStats;\n\n  constructor(config: HlsConfig) {\n    this.xhrSetup = config ? config.xhrSetup || null : null;\n    this.stats = new LoadStats();\n    this.retryDelay = 0;\n  }\n\n  destroy() {\n    this.callbacks = null;\n    this.abortInternal();\n    this.loader = null;\n    this.config = null;\n    this.context = null;\n    this.xhrSetup = null;\n  }\n\n  abortInternal() {\n    const loader = this.loader;\n    self.clearTimeout(this.requestTimeout);\n    self.clearTimeout(this.retryTimeout);\n    if (loader) {\n      loader.onreadystatechange = null;\n      loader.onprogress = null;\n      if (loader.readyState !== 4) {\n        this.stats.aborted = true;\n        loader.abort();\n      }\n    }\n  }\n\n  abort() {\n    this.abortInternal();\n    if (this.callbacks?.onAbort) {\n      this.callbacks.onAbort(\n        this.stats,\n        this.context as LoaderContext,\n        this.loader,\n      );\n    }\n  }\n\n  load(\n    context: LoaderContext,\n    config: LoaderConfiguration,\n    callbacks: LoaderCallbacks<LoaderContext>,\n  ) {\n    if (this.stats.loading.start) {\n      throw new Error('Loader can only be used once.');\n    }\n    this.stats.loading.start = self.performance.now();\n    this.context = context;\n    this.config = config;\n    this.callbacks = callbacks;\n    this.loadInternal();\n  }\n\n  loadInternal() {\n    const { config, context } = this;\n    if (!config || !context) {\n      return;\n    }\n    const xhr = (this.loader = new self.XMLHttpRequest());\n\n    const stats = this.stats;\n    stats.loading.first = 0;\n    stats.loaded = 0;\n    stats.aborted = false;\n    const xhrSetup = this.xhrSetup;\n\n    if (xhrSetup) {\n      Promise.resolve()\n        .then(() => {\n          if (this.loader !== xhr || this.stats.aborted) return;\n          return xhrSetup(xhr, context.url);\n        })\n        .catch((error: Error) => {\n          if (this.loader !== xhr || this.stats.aborted) return;\n          xhr.open('GET', context.url, true);\n          return xhrSetup(xhr, context.url);\n        })\n        .then(() => {\n          if (this.loader !== xhr || this.stats.aborted) return;\n          this.openAndSendXhr(xhr, context, config);\n        })\n        .catch((error: Error) => {\n          // IE11 throws an exception on xhr.open if attempting to access an HTTP resource over HTTPS\n          this.callbacks!.onError(\n            { code: xhr.status, text: error.message },\n            context,\n            xhr,\n            stats,\n          );\n          return;\n        });\n    } else {\n      this.openAndSendXhr(xhr, context, config);\n    }\n  }\n\n  openAndSendXhr(\n    xhr: XMLHttpRequest,\n    context: LoaderContext,\n    config: LoaderConfiguration,\n  ) {\n    if (!xhr.readyState) {\n      xhr.open('GET', context.url, true);\n    }\n\n    const headers = context.headers;\n    const { maxTimeToFirstByteMs, maxLoadTimeMs } = config.loadPolicy;\n    if (headers) {\n      for (const header in headers) {\n        xhr.setRequestHeader(header, headers[header]);\n      }\n    }\n\n    if (context.rangeEnd) {\n      xhr.setRequestHeader(\n        'Range',\n        'bytes=' + context.rangeStart + '-' + (context.rangeEnd - 1),\n      );\n    }\n\n    xhr.onreadystatechange = this.readystatechange.bind(this);\n    xhr.onprogress = this.loadprogress.bind(this);\n    xhr.responseType = context.responseType as XMLHttpRequestResponseType;\n    // setup timeout before we perform request\n    self.clearTimeout(this.requestTimeout);\n    config.timeout =\n      maxTimeToFirstByteMs && Number.isFinite(maxTimeToFirstByteMs)\n        ? maxTimeToFirstByteMs\n        : maxLoadTimeMs;\n    this.requestTimeout = self.setTimeout(\n      this.loadtimeout.bind(this),\n      config.timeout,\n    );\n    xhr.send();\n  }\n\n  readystatechange() {\n    const { context, loader: xhr, stats } = this;\n    if (!context || !xhr) {\n      return;\n    }\n    const readyState = xhr.readyState;\n    const config = this.config as LoaderConfiguration;\n\n    // don't proceed if xhr has been aborted\n    if (stats.aborted) {\n      return;\n    }\n\n    // >= HEADERS_RECEIVED\n    if (readyState >= 2) {\n      if (stats.loading.first === 0) {\n        stats.loading.first = Math.max(\n          self.performance.now(),\n          stats.loading.start,\n        );\n        // readyState >= 2 AND readyState !==4 (readyState = HEADERS_RECEIVED || LOADING) rearm timeout as xhr not finished yet\n        if (config.timeout !== config.loadPolicy.maxLoadTimeMs) {\n          self.clearTimeout(this.requestTimeout);\n          config.timeout = config.loadPolicy.maxLoadTimeMs;\n          this.requestTimeout = self.setTimeout(\n            this.loadtimeout.bind(this),\n            config.loadPolicy.maxLoadTimeMs -\n              (stats.loading.first - stats.loading.start),\n          );\n        }\n      }\n\n      if (readyState === 4) {\n        self.clearTimeout(this.requestTimeout);\n        xhr.onreadystatechange = null;\n        xhr.onprogress = null;\n        const status = xhr.status;\n        // http status between 200 to 299 are all successful\n        const useResponse = xhr.responseType !== 'text';\n        if (\n          status >= 200 &&\n          status < 300 &&\n          ((useResponse && xhr.response) || xhr.responseText !== null)\n        ) {\n          stats.loading.end = Math.max(\n            self.performance.now(),\n            stats.loading.first,\n          );\n          const data = useResponse ? xhr.response : xhr.responseText;\n          const len =\n            xhr.responseType === 'arraybuffer' ? data.byteLength : data.length;\n          stats.loaded = stats.total = len;\n          stats.bwEstimate =\n            (stats.total * 8000) / (stats.loading.end - stats.loading.first);\n          if (!this.callbacks) {\n            return;\n          }\n          const onProgress = this.callbacks.onProgress;\n          if (onProgress) {\n            onProgress(stats, context, data, xhr);\n          }\n          if (!this.callbacks) {\n            return;\n          }\n          const response: LoaderResponse = {\n            url: xhr.responseURL,\n            data: data,\n            code: status,\n          };\n\n          this.callbacks.onSuccess(response, stats, context, xhr);\n        } else {\n          const retryConfig = config.loadPolicy.errorRetry;\n          const retryCount = stats.retry;\n          // if max nb of retries reached or if http status between 400 and 499 (such error cannot be recovered, retrying is useless), return error\n          const response: LoaderResponse = {\n            url: context.url,\n            data: undefined,\n            code: status,\n          };\n          if (shouldRetry(retryConfig, retryCount, false, response)) {\n            this.retry(retryConfig);\n          } else {\n            logger.error(`${status} while loading ${context.url}`);\n            this.callbacks!.onError(\n              { code: status, text: xhr.statusText },\n              context,\n              xhr,\n              stats,\n            );\n          }\n        }\n      }\n    }\n  }\n\n  loadtimeout() {\n    if (!this.config) return;\n    const retryConfig = this.config.loadPolicy.timeoutRetry;\n    const retryCount = this.stats.retry;\n    if (shouldRetry(retryConfig, retryCount, true)) {\n      this.retry(retryConfig);\n    } else {\n      logger.warn(`timeout while loading ${this.context?.url}`);\n      const callbacks = this.callbacks;\n      if (callbacks) {\n        this.abortInternal();\n        callbacks.onTimeout(\n          this.stats,\n          this.context as LoaderContext,\n          this.loader,\n        );\n      }\n    }\n  }\n\n  retry(retryConfig: RetryConfig) {\n    const { context, stats } = this;\n    this.retryDelay = getRetryDelay(retryConfig, stats.retry);\n    stats.retry++;\n    logger.warn(\n      `${\n        status ? 'HTTP Status ' + status : 'Timeout'\n      } while loading ${context?.url}, retrying ${stats.retry}/${\n        retryConfig.maxNumRetry\n      } in ${this.retryDelay}ms`,\n    );\n    // abort and reset internal state\n    this.abortInternal();\n    this.loader = null;\n    // schedule retry\n    self.clearTimeout(this.retryTimeout);\n    this.retryTimeout = self.setTimeout(\n      this.loadInternal.bind(this),\n      this.retryDelay,\n    );\n  }\n\n  loadprogress(event: ProgressEvent) {\n    const stats = this.stats;\n\n    stats.loaded = event.loaded;\n    if (event.lengthComputable) {\n      stats.total = event.total;\n    }\n  }\n\n  getCacheAge(): number | null {\n    let result: number | null = null;\n    if (\n      this.loader &&\n      AGE_HEADER_LINE_REGEX.test(this.loader.getAllResponseHeaders())\n    ) {\n      const ageHeader = this.loader.getResponseHeader('age');\n      result = ageHeader ? parseFloat(ageHeader) : null;\n    }\n    return result;\n  }\n\n  getResponseHeader(name: string): string | null {\n    if (\n      this.loader &&\n      new RegExp(`^${name}:\\\\s*[\\\\d.]+\\\\s*$`, 'im').test(\n        this.loader.getAllResponseHeaders(),\n      )\n    ) {\n      return this.loader.getResponseHeader(name);\n    }\n    return null;\n  }\n}\n\nexport default XhrLoader;\n", "import {\n  LoaderCallbacks,\n  LoaderContext,\n  Loader,\n  LoaderStats,\n  LoaderConfiguration,\n  LoaderOnProgress,\n  LoaderResponse,\n} from '../types/loader';\nimport { LoadStats } from '../loader/load-stats';\nimport ChunkCache from '../demux/chunk-cache';\n\nexport function fetchSupported() {\n  if (\n    // @ts-ignore\n    self.fetch &&\n    self.AbortController &&\n    self.ReadableStream &&\n    self.Request\n  ) {\n    try {\n      new self.ReadableStream({}); // eslint-disable-line no-new\n      return true;\n    } catch (e) {\n      /* noop */\n    }\n  }\n  return false;\n}\n\nconst BYTERANGE = /(\\d+)-(\\d+)\\/(\\d+)/;\n\nclass FetchLoader implements Loader<LoaderContext> {\n  private fetchSetup: Function;\n  private requestTimeout?: number;\n  private request: Request | null = null;\n  private response: Response | null = null;\n  private controller: AbortController;\n  public context: LoaderContext | null = null;\n  private config: LoaderConfiguration | null = null;\n  private callbacks: LoaderCallbacks<LoaderContext> | null = null;\n  public stats: LoaderStats;\n  private loader: Response | null = null;\n\n  constructor(config /* HlsConfig */) {\n    this.fetchSetup = config.fetchSetup || getRequest;\n    this.controller = new self.AbortController();\n    this.stats = new LoadStats();\n  }\n\n  destroy(): void {\n    this.loader =\n      this.callbacks =\n      this.context =\n      this.config =\n      this.request =\n        null;\n    this.abortInternal();\n    this.response = null;\n    // @ts-ignore\n    this.fetchSetup = this.controller = this.stats = null;\n  }\n\n  abortInternal(): void {\n    if (this.controller && !this.stats.loading.end) {\n      this.stats.aborted = true;\n      this.controller.abort();\n    }\n  }\n\n  abort(): void {\n    this.abortInternal();\n    if (this.callbacks?.onAbort) {\n      this.callbacks.onAbort(\n        this.stats,\n        this.context as LoaderContext,\n        this.response,\n      );\n    }\n  }\n\n  load(\n    context: LoaderContext,\n    config: LoaderConfiguration,\n    callbacks: LoaderCallbacks<LoaderContext>,\n  ): void {\n    const stats = this.stats;\n    if (stats.loading.start) {\n      throw new Error('Loader can only be used once.');\n    }\n    stats.loading.start = self.performance.now();\n\n    const initParams = getRequestParameters(context, this.controller.signal);\n    const onProgress: LoaderOnProgress<LoaderContext> | undefined =\n      callbacks.onProgress;\n    const isArrayBuffer = context.responseType === 'arraybuffer';\n    const LENGTH = isArrayBuffer ? 'byteLength' : 'length';\n    const { maxTimeToFirstByteMs, maxLoadTimeMs } = config.loadPolicy;\n\n    this.context = context;\n    this.config = config;\n    this.callbacks = callbacks;\n    this.request = this.fetchSetup(context, initParams);\n    self.clearTimeout(this.requestTimeout);\n    config.timeout =\n      maxTimeToFirstByteMs && Number.isFinite(maxTimeToFirstByteMs)\n        ? maxTimeToFirstByteMs\n        : maxLoadTimeMs;\n    this.requestTimeout = self.setTimeout(() => {\n      this.abortInternal();\n      callbacks.onTimeout(stats, context, this.response);\n    }, config.timeout);\n\n    self\n      .fetch(this.request as Request)\n      .then((response: Response): Promise<string | ArrayBuffer> => {\n        this.response = this.loader = response;\n\n        const first = Math.max(self.performance.now(), stats.loading.start);\n\n        self.clearTimeout(this.requestTimeout);\n        config.timeout = maxLoadTimeMs;\n        this.requestTimeout = self.setTimeout(\n          () => {\n            this.abortInternal();\n            callbacks.onTimeout(stats, context, this.response);\n          },\n          maxLoadTimeMs - (first - stats.loading.start),\n        );\n\n        if (!response.ok) {\n          const { status, statusText } = response;\n          throw new FetchError(\n            statusText || 'fetch, bad network response',\n            status,\n            response,\n          );\n        }\n        stats.loading.first = first;\n\n        stats.total = getContentLength(response.headers) || stats.total;\n\n        if (onProgress && Number.isFinite(config.highWaterMark)) {\n          return this.loadProgressively(\n            response,\n            stats,\n            context,\n            config.highWaterMark,\n            onProgress,\n          );\n        }\n\n        if (isArrayBuffer) {\n          return response.arrayBuffer();\n        }\n        if (context.responseType === 'json') {\n          return response.json();\n        }\n        return response.text();\n      })\n      .then((responseData: string | ArrayBuffer) => {\n        const response = this.response;\n        if (!response) {\n          throw new Error('loader destroyed');\n        }\n        self.clearTimeout(this.requestTimeout);\n        stats.loading.end = Math.max(\n          self.performance.now(),\n          stats.loading.first,\n        );\n        const total = responseData[LENGTH];\n        if (total) {\n          stats.loaded = stats.total = total;\n        }\n\n        const loaderResponse: LoaderResponse = {\n          url: response.url,\n          data: responseData,\n          code: response.status,\n        };\n\n        if (onProgress && !Number.isFinite(config.highWaterMark)) {\n          onProgress(stats, context, responseData, response);\n        }\n\n        callbacks.onSuccess(loaderResponse, stats, context, response);\n      })\n      .catch((error) => {\n        self.clearTimeout(this.requestTimeout);\n        if (stats.aborted) {\n          return;\n        }\n        // CORS errors result in an undefined code. Set it to 0 here to align with XHR's behavior\n        // when destroying, 'error' itself can be undefined\n        const code: number = !error ? 0 : error.code || 0;\n        const text: string = !error ? null : error.message;\n        callbacks.onError(\n          { code, text },\n          context,\n          error ? error.details : null,\n          stats,\n        );\n      });\n  }\n\n  getCacheAge(): number | null {\n    let result: number | null = null;\n    if (this.response) {\n      const ageHeader = this.response.headers.get('age');\n      result = ageHeader ? parseFloat(ageHeader) : null;\n    }\n    return result;\n  }\n\n  getResponseHeader(name: string): string | null {\n    return this.response ? this.response.headers.get(name) : null;\n  }\n\n  private loadProgressively(\n    response: Response,\n    stats: LoaderStats,\n    context: LoaderContext,\n    highWaterMark: number = 0,\n    onProgress: LoaderOnProgress<LoaderContext>,\n  ): Promise<ArrayBuffer> {\n    const chunkCache = new ChunkCache();\n    const reader = (response.body as ReadableStream).getReader();\n\n    const pump = (): Promise<ArrayBuffer> => {\n      return reader\n        .read()\n        .then((data) => {\n          if (data.done) {\n            if (chunkCache.dataLength) {\n              onProgress(stats, context, chunkCache.flush(), response);\n            }\n\n            return Promise.resolve(new ArrayBuffer(0));\n          }\n          const chunk: Uint8Array = data.value;\n          const len = chunk.length;\n          stats.loaded += len;\n          if (len < highWaterMark || chunkCache.dataLength) {\n            // The current chunk is too small to to be emitted or the cache already has data\n            // Push it to the cache\n            chunkCache.push(chunk);\n            if (chunkCache.dataLength >= highWaterMark) {\n              // flush in order to join the typed arrays\n              onProgress(stats, context, chunkCache.flush(), response);\n            }\n          } else {\n            // If there's nothing cached already, and the chache is large enough\n            // just emit the progress event\n            onProgress(stats, context, chunk, response);\n          }\n          return pump();\n        })\n        .catch(() => {\n          /* aborted */\n          return Promise.reject();\n        });\n    };\n\n    return pump();\n  }\n}\n\nfunction getRequestParameters(context: LoaderContext, signal): any {\n  const initParams: any = {\n    method: 'GET',\n    mode: 'cors',\n    credentials: 'same-origin',\n    signal,\n    headers: new self.Headers(Object.assign({}, context.headers)),\n  };\n\n  if (context.rangeEnd) {\n    initParams.headers.set(\n      'Range',\n      'bytes=' + context.rangeStart + '-' + String(context.rangeEnd - 1),\n    );\n  }\n\n  return initParams;\n}\n\nfunction getByteRangeLength(byteRangeHeader: string): number | undefined {\n  const result = BYTERANGE.exec(byteRangeHeader);\n  if (result) {\n    return parseInt(result[2]) - parseInt(result[1]) + 1;\n  }\n}\n\nfunction getContentLength(headers: Headers): number | undefined {\n  const contentRange = headers.get('Content-Range');\n  if (contentRange) {\n    const byteRangeLength = getByteRangeLength(contentRange);\n    if (Number.isFinite(byteRangeLength)) {\n      return byteRangeLength;\n    }\n  }\n  const contentLength = headers.get('Content-Length');\n  if (contentLength) {\n    return parseInt(contentLength);\n  }\n}\n\nfunction getRequest(context: LoaderContext, initParams: any): Request {\n  return new self.Request(context.url, initParams);\n}\n\nclass FetchError extends Error {\n  public code: number;\n  public details: any;\n  constructor(message: string, code: number, details: any) {\n    super(message);\n    this.code = code;\n    this.details = details;\n  }\n}\n\nexport default FetchLoader;\n", "import { fixLineBreaks } from './vttparser';\nimport type { CaptionScreen, Row } from './cea-608-parser';\nimport { generateCueId } from './webvtt-parser';\nimport { addCueToTrack } from './texttrack-utils';\n\nconst WHITESPACE_CHAR = /\\s/;\n\nexport interface CuesInterface {\n  newCue(\n    track: TextTrack | null,\n    startTime: number,\n    endTime: number,\n    captionScreen: CaptionScreen,\n  ): VTTCue[];\n}\n\nconst Cues: CuesInterface = {\n  newCue(\n    track: TextTrack | null,\n    startTime: number,\n    endTime: number,\n    captionScreen: CaptionScreen,\n  ): VTTCue[] {\n    const result: VTTCue[] = [];\n    let row: Row;\n    // the type data states this is VTTCue, but it can potentially be a TextTrackCue on old browsers\n    let cue: VTTCue;\n    let indenting: boolean;\n    let indent: number;\n    let text: string;\n    const Cue = (self.VTTCue || self.TextTrackCue) as any;\n\n    for (let r = 0; r < captionScreen.rows.length; r++) {\n      row = captionScreen.rows[r];\n      indenting = true;\n      indent = 0;\n      text = '';\n\n      if (!row.isEmpty()) {\n        for (let c = 0; c < row.chars.length; c++) {\n          if (WHITESPACE_CHAR.test(row.chars[c].uchar) && indenting) {\n            indent++;\n          } else {\n            text += row.chars[c].uchar;\n            indenting = false;\n          }\n        }\n        // To be used for cleaning-up orphaned roll-up captions\n        row.cueStartTime = startTime;\n\n        // Give a slight bump to the endTime if it's equal to startTime to avoid a SyntaxError in IE\n        if (startTime === endTime) {\n          endTime += 0.0001;\n        }\n\n        if (indent >= 16) {\n          indent--;\n        } else {\n          indent++;\n        }\n\n        const cueText = fixLineBreaks(text.trim());\n        const id = generateCueId(startTime, endTime, cueText);\n\n        // If this cue already exists in the track do not push it\n        if (!track?.cues?.getCueById(id)) {\n          cue = new Cue(startTime, endTime, cueText);\n          cue.id = id;\n          cue.line = r + 1;\n          cue.align = 'left';\n          // Clamp the position between 10 and 80 percent (CEA-608 PAC indent code)\n          // https://dvcs.w3.org/hg/text-tracks/raw-file/default/608toVTT/608toVTT.html#positioning-in-cea-608\n          // Firefox throws an exception and captions break with out of bounds 0-100 values\n          cue.position = 10 + Math.min(80, Math.floor((indent * 8) / 32) * 10);\n          result.push(cue);\n        }\n      }\n    }\n    if (track && result.length) {\n      // Sort bottom cues in reverse order so that they render in line order when overlapping in Chrome\n      result.sort((cueA, cueB) => {\n        if (cueA.line === 'auto' || cueB.line === 'auto') {\n          return 0;\n        }\n        if (cueA.line > 8 && cueB.line > 8) {\n          return cueB.line - cueA.line;\n        }\n        return cueA.line - cueB.line;\n      });\n      result.forEach((cue) => addCueToTrack(track, cue));\n    }\n    return result;\n  },\n};\n\nexport default Cues;\n", "import AbrController from './controller/abr-controller';\nimport AudioStreamController from './controller/audio-stream-controller';\nimport AudioTrackController from './controller/audio-track-controller';\nimport { SubtitleStreamController } from './controller/subtitle-stream-controller';\nimport SubtitleTrackController from './controller/subtitle-track-controller';\nimport BufferController from './controller/buffer-controller';\nimport { TimelineController } from './controller/timeline-controller';\nimport CapLevelController from './controller/cap-level-controller';\nimport FPSController from './controller/fps-controller';\nimport EMEController, {\n  MediaKeySessionContext,\n} from './controller/eme-controller';\nimport CMCDController from './controller/cmcd-controller';\nimport ContentSteeringController from './controller/content-steering-controller';\nimport ErrorController from './controller/error-controller';\nimport XhrLoader from './utils/xhr-loader';\nimport FetchLoader, { fetchSupported } from './utils/fetch-loader';\nimport Cues from './utils/cues';\nimport { requestMediaKeySystemAccess } from './utils/mediakeys-helper';\nimport { ILogger, logger } from './utils/logger';\n\nimport type Hls from './hls';\nimport type { CuesInterface } from './utils/cues';\nimport type { MediaKeyFunc, KeySystems } from './utils/mediakeys-helper';\nimport type {\n  FragmentLoaderContext,\n  Loader,\n  LoaderContext,\n  LoaderResponse,\n  PlaylistLoaderContext,\n} from './types/loader';\nimport type {\n  AudioSelectionOption,\n  SubtitleSelectionOption,\n  VideoSelectionOption,\n} from './types/media-playlist';\n\nexport type ABRControllerConfig = {\n  abrEwmaFastLive: number;\n  abrEwmaSlowLive: number;\n  abrEwmaFastVoD: number;\n  abrEwmaSlowVoD: number;\n  /**\n   * Default bandwidth estimate in bits/s prior to collecting fragment bandwidth samples\n   */\n  abrEwmaDefaultEstimate: number;\n  abrEwmaDefaultEstimateMax: number;\n  abrBandWidthFactor: number;\n  abrBandWidthUpFactor: number;\n  abrMaxWithRealBitrate: boolean;\n  maxStarvationDelay: number;\n  maxLoadingDelay: number;\n};\n\nexport type BufferControllerConfig = {\n  appendErrorMaxRetry: number;\n  backBufferLength: number;\n  frontBufferFlushThreshold: number;\n  liveDurationInfinity: boolean;\n  /**\n   * @deprecated use backBufferLength\n   */\n  liveBackBufferLength: number | null;\n};\n\nexport type CapLevelControllerConfig = {\n  capLevelToPlayerSize: boolean;\n};\n\nexport type CMCDControllerConfig = {\n  sessionId?: string;\n  contentId?: string;\n  useHeaders?: boolean;\n  includeKeys?: string[];\n};\n\nexport type DRMSystemOptions = {\n  audioRobustness?: string;\n  videoRobustness?: string;\n  audioEncryptionScheme?: string | null;\n  videoEncryptionScheme?: string | null;\n  persistentState?: MediaKeysRequirement;\n  distinctiveIdentifier?: MediaKeysRequirement;\n  sessionTypes?: string[];\n  sessionType?: string;\n};\n\nexport type DRMSystemConfiguration = {\n  licenseUrl: string;\n  serverCertificateUrl?: string;\n  generateRequest?: (\n    this: Hls,\n    initDataType: string,\n    initData: ArrayBuffer | null,\n    keyContext: MediaKeySessionContext,\n  ) =>\n    | { initDataType: string; initData: ArrayBuffer | null }\n    | undefined\n    | never;\n};\n\nexport type DRMSystemsConfiguration = Partial<\n  Record<KeySystems, DRMSystemConfiguration>\n>;\n\nexport type EMEControllerConfig = {\n  licenseXhrSetup?: (\n    this: Hls,\n    xhr: XMLHttpRequest,\n    url: string,\n    keyContext: MediaKeySessionContext,\n    licenseChallenge: Uint8Array,\n  ) => void | Uint8Array | Promise<Uint8Array | void>;\n  licenseResponseCallback?: (\n    this: Hls,\n    xhr: XMLHttpRequest,\n    url: string,\n    keyContext: MediaKeySessionContext,\n  ) => ArrayBuffer;\n  emeEnabled: boolean;\n  widevineLicenseUrl?: string;\n  drmSystems: DRMSystemsConfiguration;\n  drmSystemOptions: DRMSystemOptions;\n  requestMediaKeySystemAccessFunc: MediaKeyFunc | null;\n};\n\nexport interface FragmentLoaderConstructor {\n  new (confg: HlsConfig): Loader<FragmentLoaderContext>;\n}\n\n/**\n * @deprecated use fragLoadPolicy.default\n */\nexport type FragmentLoaderConfig = {\n  fragLoadingTimeOut: number;\n  fragLoadingMaxRetry: number;\n  fragLoadingRetryDelay: number;\n  fragLoadingMaxRetryTimeout: number;\n};\n\nexport type FPSControllerConfig = {\n  capLevelOnFPSDrop: boolean;\n  fpsDroppedMonitoringPeriod: number;\n  fpsDroppedMonitoringThreshold: number;\n};\n\nexport type LevelControllerConfig = {\n  startLevel?: number;\n};\n\nexport type MP4RemuxerConfig = {\n  stretchShortVideoTrack: boolean;\n  maxAudioFramesDrift: number;\n};\n\nexport interface PlaylistLoaderConstructor {\n  new (confg: HlsConfig): Loader<PlaylistLoaderContext>;\n}\n\n/**\n * @deprecated use manifestLoadPolicy.default and playlistLoadPolicy.default\n */\nexport type PlaylistLoaderConfig = {\n  manifestLoadingTimeOut: number;\n  manifestLoadingMaxRetry: number;\n  manifestLoadingRetryDelay: number;\n  manifestLoadingMaxRetryTimeout: number;\n\n  levelLoadingTimeOut: number;\n  levelLoadingMaxRetry: number;\n  levelLoadingRetryDelay: number;\n  levelLoadingMaxRetryTimeout: number;\n};\n\nexport type HlsLoadPolicies = {\n  fragLoadPolicy: LoadPolicy;\n  keyLoadPolicy: LoadPolicy;\n  certLoadPolicy: LoadPolicy;\n  playlistLoadPolicy: LoadPolicy;\n  manifestLoadPolicy: LoadPolicy;\n  steeringManifestLoadPolicy: LoadPolicy;\n};\n\nexport type LoadPolicy = {\n  default: LoaderConfig;\n};\n\nexport type LoaderConfig = {\n  maxTimeToFirstByteMs: number; // Max time to first byte\n  maxLoadTimeMs: number; // Max time for load completion\n  timeoutRetry: RetryConfig | null;\n  errorRetry: RetryConfig | null;\n};\n\nexport type RetryConfig = {\n  maxNumRetry: number; // Maximum number of retries\n  retryDelayMs: number; // Retry delay = 2^retryCount * retryDelayMs (exponential) or retryCount * retryDelayMs (linear)\n  maxRetryDelayMs: number; // Maximum delay between retries\n  backoff?: 'exponential' | 'linear'; // used to determine retry backoff duration (see retryDelayMs)\n  shouldRetry?: (\n    retryConfig: RetryConfig | null | undefined,\n    retryCount: number,\n    isTimeout: boolean,\n    loaderResponse: LoaderResponse | undefined,\n    retry: boolean,\n  ) => boolean;\n};\n\nexport type StreamControllerConfig = {\n  autoStartLoad: boolean;\n  startPosition: number;\n  defaultAudioCodec?: string;\n  initialLiveManifestSize: number;\n  maxBufferLength: number;\n  maxBufferSize: number;\n  maxBufferHole: number;\n  highBufferWatchdogPeriod: number;\n  nudgeOffset: number;\n  nudgeMaxRetry: number;\n  maxFragLookUpTolerance: number;\n  maxMaxBufferLength: number;\n  startFragPrefetch: boolean;\n  testBandwidth: boolean;\n};\n\nexport type SelectionPreferences = {\n  videoPreference?: VideoSelectionOption;\n  audioPreference?: AudioSelectionOption;\n  subtitlePreference?: SubtitleSelectionOption;\n};\n\nexport type LatencyControllerConfig = {\n  liveSyncDurationCount: number;\n  liveMaxLatencyDurationCount: number;\n  liveSyncDuration?: number;\n  liveMaxLatencyDuration?: number;\n  maxLiveSyncPlaybackRate: number;\n};\n\nexport type MetadataControllerConfig = {\n  enableDateRangeMetadataCues: boolean;\n  enableEmsgMetadataCues: boolean;\n  enableID3MetadataCues: boolean;\n};\n\nexport type TimelineControllerConfig = {\n  cueHandler: CuesInterface;\n  enableWebVTT: boolean;\n  enableIMSC1: boolean;\n  enableCEA708Captions: boolean;\n  captionsTextTrack1Label: string;\n  captionsTextTrack1LanguageCode: string;\n  captionsTextTrack2Label: string;\n  captionsTextTrack2LanguageCode: string;\n  captionsTextTrack3Label: string;\n  captionsTextTrack3LanguageCode: string;\n  captionsTextTrack4Label: string;\n  captionsTextTrack4LanguageCode: string;\n  renderTextTracksNatively: boolean;\n};\n\nexport type TSDemuxerConfig = {\n  forceKeyFrameOnDiscontinuity: boolean;\n};\n\nexport type HlsConfig = {\n  debug: boolean | ILogger;\n  enableWorker: boolean;\n  workerPath: null | string;\n  enableSoftwareAES: boolean;\n  minAutoBitrate: number;\n  ignoreDevicePixelRatio: boolean;\n  preferManagedMediaSource: boolean;\n  loader: { new (confg: HlsConfig): Loader<LoaderContext> };\n  fLoader?: FragmentLoaderConstructor;\n  pLoader?: PlaylistLoaderConstructor;\n  fetchSetup?: (context: LoaderContext, initParams: any) => Request;\n  xhrSetup?: (xhr: XMLHttpRequest, url: string) => Promise<void> | void;\n\n  // Alt Audio\n  audioStreamController?: typeof AudioStreamController;\n  audioTrackController?: typeof AudioTrackController;\n  // Subtitle\n  subtitleStreamController?: typeof SubtitleStreamController;\n  subtitleTrackController?: typeof SubtitleTrackController;\n  timelineController?: typeof TimelineController;\n  // EME\n  emeController?: typeof EMEController;\n  // CMCD\n  cmcd?: CMCDControllerConfig;\n  cmcdController?: typeof CMCDController;\n  // Content Steering\n  contentSteeringController?: typeof ContentSteeringController;\n\n  // MediaCapabilies API for level, track, and switch filtering\n  useMediaCapabilities: boolean;\n\n  abrController: typeof AbrController;\n  bufferController: typeof BufferController;\n  capLevelController: typeof CapLevelController;\n  errorController: typeof ErrorController;\n  fpsController: typeof FPSController;\n  progressive: boolean;\n  lowLatencyMode: boolean;\n} & ABRControllerConfig &\n  BufferControllerConfig &\n  CapLevelControllerConfig &\n  EMEControllerConfig &\n  FPSControllerConfig &\n  LevelControllerConfig &\n  MP4RemuxerConfig &\n  StreamControllerConfig &\n  SelectionPreferences &\n  LatencyControllerConfig &\n  MetadataControllerConfig &\n  TimelineControllerConfig &\n  TSDemuxerConfig &\n  HlsLoadPolicies &\n  FragmentLoaderConfig &\n  PlaylistLoaderConfig;\n\nconst defaultLoadPolicy: LoaderConfig = {\n  maxTimeToFirstByteMs: 8000,\n  maxLoadTimeMs: 20000,\n  timeoutRetry: null,\n  errorRetry: null,\n};\n\n/**\n * @ignore\n * If possible, keep hlsDefaultConfig shallow\n * It is cloned whenever a new Hls instance is created, by keeping the config\n * shallow the properties are cloned, and we don't end up manipulating the default\n */\nexport const hlsDefaultConfig: HlsConfig = {\n  autoStartLoad: true, // used by stream-controller\n  startPosition: -1, // used by stream-controller\n  defaultAudioCodec: undefined, // used by stream-controller\n  debug: false, // used by logger\n  capLevelOnFPSDrop: false, // used by fps-controller\n  capLevelToPlayerSize: false, // used by cap-level-controller\n  ignoreDevicePixelRatio: false, // used by cap-level-controller\n  preferManagedMediaSource: true,\n  initialLiveManifestSize: 1, // used by stream-controller\n  maxBufferLength: 30, // used by stream-controller\n  backBufferLength: Infinity, // used by buffer-controller\n  frontBufferFlushThreshold: Infinity,\n  maxBufferSize: 60 * 1000 * 1000, // used by stream-controller\n  maxBufferHole: 0.1, // used by stream-controller\n  highBufferWatchdogPeriod: 2, // used by stream-controller\n  nudgeOffset: 0.1, // used by stream-controller\n  nudgeMaxRetry: 3, // used by stream-controller\n  maxFragLookUpTolerance: 0.25, // used by stream-controller\n  liveSyncDurationCount: 3, // used by latency-controller\n  liveMaxLatencyDurationCount: Infinity, // used by latency-controller\n  liveSyncDuration: undefined, // used by latency-controller\n  liveMaxLatencyDuration: undefined, // used by latency-controller\n  maxLiveSyncPlaybackRate: 1, // used by latency-controller\n  liveDurationInfinity: false, // used by buffer-controller\n  /**\n   * @deprecated use backBufferLength\n   */\n  liveBackBufferLength: null, // used by buffer-controller\n  maxMaxBufferLength: 600, // used by stream-controller\n  enableWorker: true, // used by transmuxer\n  workerPath: null, // used by transmuxer\n  enableSoftwareAES: true, // used by decrypter\n  startLevel: undefined, // used by level-controller\n  startFragPrefetch: false, // used by stream-controller\n  fpsDroppedMonitoringPeriod: 5000, // used by fps-controller\n  fpsDroppedMonitoringThreshold: 0.2, // used by fps-controller\n  appendErrorMaxRetry: 3, // used by buffer-controller\n  loader: XhrLoader,\n  // loader: FetchLoader,\n  fLoader: undefined, // used by fragment-loader\n  pLoader: undefined, // used by playlist-loader\n  xhrSetup: undefined, // used by xhr-loader\n  licenseXhrSetup: undefined, // used by eme-controller\n  licenseResponseCallback: undefined, // used by eme-controller\n  abrController: AbrController,\n  bufferController: BufferController,\n  capLevelController: CapLevelController,\n  errorController: ErrorController,\n  fpsController: FPSController,\n  stretchShortVideoTrack: false, // used by mp4-remuxer\n  maxAudioFramesDrift: 1, // used by mp4-remuxer\n  forceKeyFrameOnDiscontinuity: true, // used by ts-demuxer\n  abrEwmaFastLive: 3, // used by abr-controller\n  abrEwmaSlowLive: 9, // used by abr-controller\n  abrEwmaFastVoD: 3, // used by abr-controller\n  abrEwmaSlowVoD: 9, // used by abr-controller\n  abrEwmaDefaultEstimate: 5e5, // 500 kbps  // used by abr-controller\n  abrEwmaDefaultEstimateMax: 5e6, // 5 mbps\n  abrBandWidthFactor: 0.95, // used by abr-controller\n  abrBandWidthUpFactor: 0.7, // used by abr-controller\n  abrMaxWithRealBitrate: false, // used by abr-controller\n  maxStarvationDelay: 4, // used by abr-controller\n  maxLoadingDelay: 4, // used by abr-controller\n  minAutoBitrate: 0, // used by hls\n  emeEnabled: false, // used by eme-controller\n  widevineLicenseUrl: undefined, // used by eme-controller\n  drmSystems: {}, // used by eme-controller\n  drmSystemOptions: {}, // used by eme-controller\n  requestMediaKeySystemAccessFunc: __USE_EME_DRM__\n    ? requestMediaKeySystemAccess\n    : null, // used by eme-controller\n  testBandwidth: true,\n  progressive: false,\n  lowLatencyMode: true,\n  cmcd: undefined,\n  enableDateRangeMetadataCues: true,\n  enableEmsgMetadataCues: true,\n  enableID3MetadataCues: true,\n  useMediaCapabilities: __USE_MEDIA_CAPABILITIES__,\n\n  certLoadPolicy: {\n    default: defaultLoadPolicy,\n  },\n  keyLoadPolicy: {\n    default: {\n      maxTimeToFirstByteMs: 8000,\n      maxLoadTimeMs: 20000,\n      timeoutRetry: {\n        maxNumRetry: 1,\n        retryDelayMs: 1000,\n        maxRetryDelayMs: 20000,\n        backoff: 'linear',\n      },\n      errorRetry: {\n        maxNumRetry: 8,\n        retryDelayMs: 1000,\n        maxRetryDelayMs: 20000,\n        backoff: 'linear',\n      },\n    },\n  },\n  manifestLoadPolicy: {\n    default: {\n      maxTimeToFirstByteMs: Infinity,\n      maxLoadTimeMs: 20000,\n      timeoutRetry: {\n        maxNumRetry: 2,\n        retryDelayMs: 0,\n        maxRetryDelayMs: 0,\n      },\n      errorRetry: {\n        maxNumRetry: 1,\n        retryDelayMs: 1000,\n        maxRetryDelayMs: 8000,\n      },\n    },\n  },\n  playlistLoadPolicy: {\n    default: {\n      maxTimeToFirstByteMs: 10000,\n      maxLoadTimeMs: 20000,\n      timeoutRetry: {\n        maxNumRetry: 2,\n        retryDelayMs: 0,\n        maxRetryDelayMs: 0,\n      },\n      errorRetry: {\n        maxNumRetry: 2,\n        retryDelayMs: 1000,\n        maxRetryDelayMs: 8000,\n      },\n    },\n  },\n  fragLoadPolicy: {\n    default: {\n      maxTimeToFirstByteMs: 10000,\n      maxLoadTimeMs: 120000,\n      timeoutRetry: {\n        maxNumRetry: 4,\n        retryDelayMs: 0,\n        maxRetryDelayMs: 0,\n      },\n      errorRetry: {\n        maxNumRetry: 6,\n        retryDelayMs: 1000,\n        maxRetryDelayMs: 8000,\n      },\n    },\n  },\n  steeringManifestLoadPolicy: {\n    default: __USE_CONTENT_STEERING__\n      ? {\n          maxTimeToFirstByteMs: 10000,\n          maxLoadTimeMs: 20000,\n          timeoutRetry: {\n            maxNumRetry: 2,\n            retryDelayMs: 0,\n            maxRetryDelayMs: 0,\n          },\n          errorRetry: {\n            maxNumRetry: 1,\n            retryDelayMs: 1000,\n            maxRetryDelayMs: 8000,\n          },\n        }\n      : defaultLoadPolicy,\n  },\n\n  // These default settings are deprecated in favor of the above policies\n  // and are maintained for backwards compatibility\n  manifestLoadingTimeOut: 10000,\n  manifestLoadingMaxRetry: 1,\n  manifestLoadingRetryDelay: 1000,\n  manifestLoadingMaxRetryTimeout: 64000,\n  levelLoadingTimeOut: 10000,\n  levelLoadingMaxRetry: 4,\n  levelLoadingRetryDelay: 1000,\n  levelLoadingMaxRetryTimeout: 64000,\n  fragLoadingTimeOut: 20000,\n  fragLoadingMaxRetry: 6,\n  fragLoadingRetryDelay: 1000,\n  fragLoadingMaxRetryTimeout: 64000,\n\n  // Dynamic Modules\n  ...timelineConfig(),\n  subtitleStreamController: __USE_SUBTITLES__\n    ? SubtitleStreamController\n    : undefined,\n  subtitleTrackController: __USE_SUBTITLES__\n    ? SubtitleTrackController\n    : undefined,\n  timelineController: __USE_SUBTITLES__ ? TimelineController : undefined,\n  audioStreamController: __USE_ALT_AUDIO__ ? AudioStreamController : undefined,\n  audioTrackController: __USE_ALT_AUDIO__ ? AudioTrackController : undefined,\n  emeController: __USE_EME_DRM__ ? EMEController : undefined,\n  cmcdController: __USE_CMCD__ ? CMCDController : undefined,\n  contentSteeringController: __USE_CONTENT_STEERING__\n    ? ContentSteeringController\n    : undefined,\n};\n\nfunction timelineConfig(): TimelineControllerConfig {\n  return {\n    cueHandler: Cues, // used by timeline-controller\n    enableWebVTT: __USE_SUBTITLES__, // used by timeline-controller\n    enableIMSC1: __USE_SUBTITLES__, // used by timeline-controller\n    enableCEA708Captions: __USE_SUBTITLES__, // used by timeline-controller\n    captionsTextTrack1Label: 'English', // used by timeline-controller\n    captionsTextTrack1LanguageCode: 'en', // used by timeline-controller\n    captionsTextTrack2Label: 'Spanish', // used by timeline-controller\n    captionsTextTrack2LanguageCode: 'es', // used by timeline-controller\n    captionsTextTrack3Label: 'Unknown CC', // used by timeline-controller\n    captionsTextTrack3LanguageCode: '', // used by timeline-controller\n    captionsTextTrack4Label: 'Unknown CC', // used by timeline-controller\n    captionsTextTrack4LanguageCode: '', // used by timeline-controller\n    renderTextTracksNatively: true,\n  };\n}\n\n/**\n * @ignore\n */\nexport function mergeConfig(\n  defaultConfig: HlsConfig,\n  userConfig: Partial<HlsConfig>,\n): HlsConfig {\n  if (\n    (userConfig.liveSyncDurationCount ||\n      userConfig.liveMaxLatencyDurationCount) &&\n    (userConfig.liveSyncDuration || userConfig.liveMaxLatencyDuration)\n  ) {\n    throw new Error(\n      \"Illegal hls.js config: don't mix up liveSyncDurationCount/liveMaxLatencyDurationCount and liveSyncDuration/liveMaxLatencyDuration\",\n    );\n  }\n\n  if (\n    userConfig.liveMaxLatencyDurationCount !== undefined &&\n    (userConfig.liveSyncDurationCount === undefined ||\n      userConfig.liveMaxLatencyDurationCount <=\n        userConfig.liveSyncDurationCount)\n  ) {\n    throw new Error(\n      'Illegal hls.js config: \"liveMaxLatencyDurationCount\" must be greater than \"liveSyncDurationCount\"',\n    );\n  }\n\n  if (\n    userConfig.liveMaxLatencyDuration !== undefined &&\n    (userConfig.liveSyncDuration === undefined ||\n      userConfig.liveMaxLatencyDuration <= userConfig.liveSyncDuration)\n  ) {\n    throw new Error(\n      'Illegal hls.js config: \"liveMaxLatencyDuration\" must be greater than \"liveSyncDuration\"',\n    );\n  }\n\n  const defaultsCopy = deepCpy(defaultConfig);\n\n  // Backwards compatibility with deprecated config values\n  const deprecatedSettingTypes = ['manifest', 'level', 'frag'];\n  const deprecatedSettings = [\n    'TimeOut',\n    'MaxRetry',\n    'RetryDelay',\n    'MaxRetryTimeout',\n  ];\n  deprecatedSettingTypes.forEach((type) => {\n    const policyName = `${type === 'level' ? 'playlist' : type}LoadPolicy`;\n    const policyNotSet = userConfig[policyName] === undefined;\n    const report: string[] = [];\n    deprecatedSettings.forEach((setting) => {\n      const deprecatedSetting = `${type}Loading${setting}`;\n      const value = userConfig[deprecatedSetting];\n      if (value !== undefined && policyNotSet) {\n        report.push(deprecatedSetting);\n        const settings: LoaderConfig = defaultsCopy[policyName].default;\n        userConfig[policyName] = { default: settings };\n        switch (setting) {\n          case 'TimeOut':\n            settings.maxLoadTimeMs = value;\n            settings.maxTimeToFirstByteMs = value;\n            break;\n          case 'MaxRetry':\n            settings.errorRetry!.maxNumRetry = value;\n            settings.timeoutRetry!.maxNumRetry = value;\n            break;\n          case 'RetryDelay':\n            settings.errorRetry!.retryDelayMs = value;\n            settings.timeoutRetry!.retryDelayMs = value;\n            break;\n          case 'MaxRetryTimeout':\n            settings.errorRetry!.maxRetryDelayMs = value;\n            settings.timeoutRetry!.maxRetryDelayMs = value;\n            break;\n        }\n      }\n    });\n    if (report.length) {\n      logger.warn(\n        `hls.js config: \"${report.join(\n          '\", \"',\n        )}\" setting(s) are deprecated, use \"${policyName}\": ${JSON.stringify(\n          userConfig[policyName],\n        )}`,\n      );\n    }\n  });\n\n  return {\n    ...defaultsCopy,\n    ...userConfig,\n  };\n}\n\nfunction deepCpy(obj: any): any {\n  if (obj && typeof obj === 'object') {\n    if (Array.isArray(obj)) {\n      return obj.map(deepCpy);\n    }\n    return Object.keys(obj).reduce((result, key) => {\n      result[key] = deepCpy(obj[key]);\n      return result;\n    }, {});\n  }\n  return obj;\n}\n\n/**\n * @ignore\n */\nexport function enableStreamingMode(config) {\n  const currentLoader = config.loader;\n  if (currentLoader !== FetchLoader && currentLoader !== XhrLoader) {\n    // If a developer has configured their own loader, respect that choice\n    logger.log(\n      '[config]: Custom loader detected, cannot enable progressive streaming',\n    );\n    config.progressive = false;\n  } else {\n    const canStreamProgressively = fetchSupported();\n    if (canStreamProgressively) {\n      config.loader = FetchLoader;\n      config.progressive = true;\n      config.enableSoftwareAES = true;\n      logger.log('[config]: Progressive streaming enabled, using FetchLoader');\n    }\n  }\n}\n", "import {\n  ManifestLoadedData,\n  ManifestParsedData,\n  LevelLoadedData,\n  ErrorData,\n  LevelSwitchingData,\n  LevelsUpdatedData,\n  ManifestLoadingData,\n  FragBufferedData,\n} from '../types/events';\nimport { Level, VideoRangeValues, isVideoRange } from '../types/level';\nimport { Events } from '../events';\nimport { ErrorTypes, ErrorDetails } from '../errors';\nimport {\n  areCodecsMediaSourceSupported,\n  codecsSetSelectionPreferenceValue,\n  convertAVC1ToAVCOTI,\n  getCodecCompatibleName,\n  videoCodecPreferenceValue,\n} from '../utils/codecs';\nimport BasePlaylistController from './base-playlist-controller';\nimport { PlaylistContextType, PlaylistLevelType } from '../types/loader';\nimport ContentSteeringController from './content-steering-controller';\nimport { reassignFragmentLevelIndexes } from '../utils/level-helper';\nimport { hlsDefaultConfig } from '../config';\nimport type Hls from '../hls';\nimport type { HlsUrlParameters, LevelParsed } from '../types/level';\nimport type { MediaPlaylist } from '../types/media-playlist';\n\nlet chromeOrFirefox: boolean;\n\nexport default class LevelController extends BasePlaylistController {\n  private _levels: Level[] = [];\n  private _firstLevel: number = -1;\n  private _maxAutoLevel: number = -1;\n  private _startLevel?: number;\n  private currentLevel: Level | null = null;\n  private currentLevelIndex: number = -1;\n  private manualLevelIndex: number = -1;\n  private steering: ContentSteeringController | null;\n\n  public onParsedComplete!: Function;\n\n  constructor(\n    hls: Hls,\n    contentSteeringController: ContentSteeringController | null,\n  ) {\n    super(hls, '[level-controller]');\n    this.steering = contentSteeringController;\n    this._registerListeners();\n  }\n\n  private _registerListeners() {\n    const { hls } = this;\n    hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    hls.on(Events.MANIFEST_LOADED, this.onManifestLoaded, this);\n    hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);\n    hls.on(Events.LEVELS_UPDATED, this.onLevelsUpdated, this);\n    hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);\n    hls.on(Events.ERROR, this.onError, this);\n  }\n\n  private _unregisterListeners() {\n    const { hls } = this;\n    hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    hls.off(Events.MANIFEST_LOADED, this.onManifestLoaded, this);\n    hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);\n    hls.off(Events.LEVELS_UPDATED, this.onLevelsUpdated, this);\n    hls.off(Events.FRAG_BUFFERED, this.onFragBuffered, this);\n    hls.off(Events.ERROR, this.onError, this);\n  }\n\n  public destroy() {\n    this._unregisterListeners();\n    this.steering = null;\n    this.resetLevels();\n    super.destroy();\n  }\n\n  public stopLoad(): void {\n    const levels = this._levels;\n\n    // clean up live level details to force reload them, and reset load errors\n    levels.forEach((level) => {\n      level.loadError = 0;\n      level.fragmentError = 0;\n    });\n\n    super.stopLoad();\n  }\n\n  private resetLevels() {\n    this._startLevel = undefined;\n    this.manualLevelIndex = -1;\n    this.currentLevelIndex = -1;\n    this.currentLevel = null;\n    this._levels = [];\n    this._maxAutoLevel = -1;\n  }\n\n  private onManifestLoading(\n    event: Events.MANIFEST_LOADING,\n    data: ManifestLoadingData,\n  ) {\n    this.resetLevels();\n  }\n\n  protected onManifestLoaded(\n    event: Events.MANIFEST_LOADED,\n    data: ManifestLoadedData,\n  ) {\n    const preferManagedMediaSource = this.hls.config.preferManagedMediaSource;\n    const levels: Level[] = [];\n    const redundantSet: { [key: string]: Level } = {};\n    const generatePathwaySet: { [key: string]: number } = {};\n    let resolutionFound = false;\n    let videoCodecFound = false;\n    let audioCodecFound = false;\n\n    data.levels.forEach((levelParsed: LevelParsed) => {\n      const attributes = levelParsed.attrs;\n\n      // erase audio codec info if browser does not support mp4a.40.34.\n      // demuxer will autodetect codec and fallback to mpeg/audio\n      let { audioCodec, videoCodec } = levelParsed;\n      if (audioCodec?.indexOf('mp4a.40.34') !== -1) {\n        chromeOrFirefox ||= /chrome|firefox/i.test(navigator.userAgent);\n        if (chromeOrFirefox) {\n          levelParsed.audioCodec = audioCodec = undefined;\n        }\n      }\n\n      if (audioCodec) {\n        levelParsed.audioCodec = audioCodec = getCodecCompatibleName(\n          audioCodec,\n          preferManagedMediaSource,\n        );\n      }\n\n      if (videoCodec?.indexOf('avc1') === 0) {\n        videoCodec = levelParsed.videoCodec = convertAVC1ToAVCOTI(videoCodec);\n      }\n\n      // only keep levels with supported audio/video codecs\n      const { width, height, unknownCodecs } = levelParsed;\n      resolutionFound ||= !!(width && height);\n      videoCodecFound ||= !!videoCodec;\n      audioCodecFound ||= !!audioCodec;\n      if (\n        unknownCodecs?.length ||\n        (audioCodec &&\n          !areCodecsMediaSourceSupported(\n            audioCodec,\n            'audio',\n            preferManagedMediaSource,\n          )) ||\n        (videoCodec &&\n          !areCodecsMediaSourceSupported(\n            videoCodec,\n            'video',\n            preferManagedMediaSource,\n          ))\n      ) {\n        return;\n      }\n\n      const {\n        CODECS,\n        'FRAME-RATE': FRAMERATE,\n        'HDCP-LEVEL': HDCP,\n        'PATHWAY-ID': PATHWAY,\n        RESOLUTION,\n        'VIDEO-RANGE': VIDEO_RANGE,\n      } = attributes;\n      const contentSteeringPrefix = `${PATHWAY || '.'}-`;\n      const levelKey = `${contentSteeringPrefix}${levelParsed.bitrate}-${RESOLUTION}-${FRAMERATE}-${CODECS}-${VIDEO_RANGE}-${HDCP}`;\n\n      if (!redundantSet[levelKey]) {\n        const level = new Level(levelParsed);\n        redundantSet[levelKey] = level;\n        generatePathwaySet[levelKey] = 1;\n        levels.push(level);\n      } else if (\n        redundantSet[levelKey].uri !== levelParsed.url &&\n        !levelParsed.attrs['PATHWAY-ID']\n      ) {\n        // Assign Pathway IDs to Redundant Streams (default Pathways is \".\". Redundant Streams \"..\", \"...\", and so on.)\n        // Content Steering controller to handles Pathway fallback on error\n        const pathwayCount = (generatePathwaySet[levelKey] += 1);\n        levelParsed.attrs['PATHWAY-ID'] = new Array(pathwayCount + 1).join('.');\n        const level = new Level(levelParsed);\n        redundantSet[levelKey] = level;\n        levels.push(level);\n      } else {\n        redundantSet[levelKey].addGroupId('audio', attributes.AUDIO);\n        redundantSet[levelKey].addGroupId('text', attributes.SUBTITLES);\n      }\n    });\n\n    this.filterAndSortMediaOptions(\n      levels,\n      data,\n      resolutionFound,\n      videoCodecFound,\n      audioCodecFound,\n    );\n  }\n\n  private filterAndSortMediaOptions(\n    filteredLevels: Level[],\n    data: ManifestLoadedData,\n    resolutionFound: boolean,\n    videoCodecFound: boolean,\n    audioCodecFound: boolean,\n  ) {\n    let audioTracks: MediaPlaylist[] = [];\n    let subtitleTracks: MediaPlaylist[] = [];\n    let levels = filteredLevels;\n\n    // remove audio-only and invalid video-range levels if we also have levels with video codecs or RESOLUTION signalled\n    if ((resolutionFound || videoCodecFound) && audioCodecFound) {\n      levels = levels.filter(\n        ({ videoCodec, videoRange, width, height }) =>\n          (!!videoCodec || !!(width && height)) && isVideoRange(videoRange),\n      );\n    }\n\n    if (levels.length === 0) {\n      // Dispatch error after MANIFEST_LOADED is done propagating\n      Promise.resolve().then(() => {\n        if (this.hls) {\n          if (data.levels.length) {\n            this.warn(\n              `One or more CODECS in variant not supported: ${JSON.stringify(\n                data.levels[0].attrs,\n              )}`,\n            );\n          }\n          const error = new Error(\n            'no level with compatible codecs found in manifest',\n          );\n          this.hls.trigger(Events.ERROR, {\n            type: ErrorTypes.MEDIA_ERROR,\n            details: ErrorDetails.MANIFEST_INCOMPATIBLE_CODECS_ERROR,\n            fatal: true,\n            url: data.url,\n            error,\n            reason: error.message,\n          });\n        }\n      });\n      return;\n    }\n\n    if (data.audioTracks) {\n      const { preferManagedMediaSource } = this.hls.config;\n      audioTracks = data.audioTracks.filter(\n        (track) =>\n          !track.audioCodec ||\n          areCodecsMediaSourceSupported(\n            track.audioCodec,\n            'audio',\n            preferManagedMediaSource,\n          ),\n      );\n      // Assign ids after filtering as array indices by group-id\n      assignTrackIdsByGroup(audioTracks);\n    }\n\n    if (data.subtitles) {\n      subtitleTracks = data.subtitles;\n      assignTrackIdsByGroup(subtitleTracks);\n    }\n    // start bitrate is the first bitrate of the manifest\n    const unsortedLevels = levels.slice(0);\n    // sort levels from lowest to highest\n    levels.sort((a, b) => {\n      if (a.attrs['HDCP-LEVEL'] !== b.attrs['HDCP-LEVEL']) {\n        return (a.attrs['HDCP-LEVEL'] || '') > (b.attrs['HDCP-LEVEL'] || '')\n          ? 1\n          : -1;\n      }\n      // sort on height before bitrate for cap-level-controller\n      if (resolutionFound && a.height !== b.height) {\n        return a.height - b.height;\n      }\n      if (a.frameRate !== b.frameRate) {\n        return a.frameRate - b.frameRate;\n      }\n      if (a.videoRange !== b.videoRange) {\n        return (\n          VideoRangeValues.indexOf(a.videoRange) -\n          VideoRangeValues.indexOf(b.videoRange)\n        );\n      }\n      if (a.videoCodec !== b.videoCodec) {\n        const valueA = videoCodecPreferenceValue(a.videoCodec);\n        const valueB = videoCodecPreferenceValue(b.videoCodec);\n        if (valueA !== valueB) {\n          return valueB - valueA;\n        }\n      }\n      if (a.uri === b.uri && a.codecSet !== b.codecSet) {\n        const valueA = codecsSetSelectionPreferenceValue(a.codecSet);\n        const valueB = codecsSetSelectionPreferenceValue(b.codecSet);\n        if (valueA !== valueB) {\n          return valueB - valueA;\n        }\n      }\n      if (a.averageBitrate !== b.averageBitrate) {\n        return a.averageBitrate - b.averageBitrate;\n      }\n      return 0;\n    });\n\n    let firstLevelInPlaylist = unsortedLevels[0];\n    if (this.steering) {\n      levels = this.steering.filterParsedLevels(levels);\n      if (levels.length !== unsortedLevels.length) {\n        for (let i = 0; i < unsortedLevels.length; i++) {\n          if (unsortedLevels[i].pathwayId === levels[0].pathwayId) {\n            firstLevelInPlaylist = unsortedLevels[i];\n            break;\n          }\n        }\n      }\n    }\n\n    this._levels = levels;\n\n    // find index of first level in sorted levels\n    for (let i = 0; i < levels.length; i++) {\n      if (levels[i] === firstLevelInPlaylist) {\n        this._firstLevel = i;\n        const firstLevelBitrate = firstLevelInPlaylist.bitrate;\n        const bandwidthEstimate = this.hls.bandwidthEstimate;\n        this.log(\n          `manifest loaded, ${levels.length} level(s) found, first bitrate: ${firstLevelBitrate}`,\n        );\n        // Update default bwe to first variant bitrate as long it has not been configured or set\n        if (this.hls.userConfig?.abrEwmaDefaultEstimate === undefined) {\n          const startingBwEstimate = Math.min(\n            firstLevelBitrate,\n            this.hls.config.abrEwmaDefaultEstimateMax,\n          );\n          if (\n            startingBwEstimate > bandwidthEstimate &&\n            bandwidthEstimate === hlsDefaultConfig.abrEwmaDefaultEstimate\n          ) {\n            this.hls.bandwidthEstimate = startingBwEstimate;\n          }\n        }\n        break;\n      }\n    }\n\n    // Audio is only alternate if manifest include a URI along with the audio group tag,\n    // and this is not an audio-only stream where levels contain audio-only\n    const audioOnly = audioCodecFound && !videoCodecFound;\n    const edata: ManifestParsedData = {\n      levels,\n      audioTracks,\n      subtitleTracks,\n      sessionData: data.sessionData,\n      sessionKeys: data.sessionKeys,\n      firstLevel: this._firstLevel,\n      stats: data.stats,\n      audio: audioCodecFound,\n      video: videoCodecFound,\n      altAudio: !audioOnly && audioTracks.some((t) => !!t.url),\n    };\n    this.hls.trigger(Events.MANIFEST_PARSED, edata);\n\n    // Initiate loading after all controllers have received MANIFEST_PARSED\n    if (this.hls.config.autoStartLoad || this.hls.forceStartLoad) {\n      this.hls.startLoad(this.hls.config.startPosition);\n    }\n  }\n\n  get levels(): Level[] | null {\n    if (this._levels.length === 0) {\n      return null;\n    }\n    return this._levels;\n  }\n\n  get level(): number {\n    return this.currentLevelIndex;\n  }\n\n  set level(newLevel: number) {\n    const levels = this._levels;\n    if (levels.length === 0) {\n      return;\n    }\n    // check if level idx is valid\n    if (newLevel < 0 || newLevel >= levels.length) {\n      // invalid level id given, trigger error\n      const error = new Error('invalid level idx');\n      const fatal = newLevel < 0;\n      this.hls.trigger(Events.ERROR, {\n        type: ErrorTypes.OTHER_ERROR,\n        details: ErrorDetails.LEVEL_SWITCH_ERROR,\n        level: newLevel,\n        fatal,\n        error,\n        reason: error.message,\n      });\n      if (fatal) {\n        return;\n      }\n      newLevel = Math.min(newLevel, levels.length - 1);\n    }\n\n    const lastLevelIndex = this.currentLevelIndex;\n    const lastLevel = this.currentLevel;\n    const lastPathwayId = lastLevel ? lastLevel.attrs['PATHWAY-ID'] : undefined;\n    const level = levels[newLevel];\n    const pathwayId = level.attrs['PATHWAY-ID'];\n    this.currentLevelIndex = newLevel;\n    this.currentLevel = level;\n\n    if (\n      lastLevelIndex === newLevel &&\n      level.details &&\n      lastLevel &&\n      lastPathwayId === pathwayId\n    ) {\n      return;\n    }\n\n    this.log(\n      `Switching to level ${newLevel} (${\n        level.height ? level.height + 'p ' : ''\n      }${level.videoRange ? level.videoRange + ' ' : ''}${\n        level.codecSet ? level.codecSet + ' ' : ''\n      }@${level.bitrate})${\n        pathwayId ? ' with Pathway ' + pathwayId : ''\n      } from level ${lastLevelIndex}${\n        lastPathwayId ? ' with Pathway ' + lastPathwayId : ''\n      }`,\n    );\n\n    const levelSwitchingData: LevelSwitchingData = {\n      level: newLevel,\n      attrs: level.attrs,\n      details: level.details,\n      bitrate: level.bitrate,\n      averageBitrate: level.averageBitrate,\n      maxBitrate: level.maxBitrate,\n      realBitrate: level.realBitrate,\n      width: level.width,\n      height: level.height,\n      codecSet: level.codecSet,\n      audioCodec: level.audioCodec,\n      videoCodec: level.videoCodec,\n      audioGroups: level.audioGroups,\n      subtitleGroups: level.subtitleGroups,\n      loaded: level.loaded,\n      loadError: level.loadError,\n      fragmentError: level.fragmentError,\n      name: level.name,\n      id: level.id,\n      uri: level.uri,\n      url: level.url,\n      urlId: 0,\n      audioGroupIds: level.audioGroupIds,\n      textGroupIds: level.textGroupIds,\n    };\n\n    this.hls.trigger(Events.LEVEL_SWITCHING, levelSwitchingData);\n    // check if we need to load playlist for this level\n    const levelDetails = level.details;\n    if (!levelDetails || levelDetails.live) {\n      // level not retrieved yet, or live playlist we need to (re)load it\n      const hlsUrlParameters = this.switchParams(\n        level.uri,\n        lastLevel?.details,\n        levelDetails,\n      );\n      this.loadPlaylist(hlsUrlParameters);\n    }\n  }\n\n  get manualLevel(): number {\n    return this.manualLevelIndex;\n  }\n\n  set manualLevel(newLevel) {\n    this.manualLevelIndex = newLevel;\n    if (this._startLevel === undefined) {\n      this._startLevel = newLevel;\n    }\n\n    if (newLevel !== -1) {\n      this.level = newLevel;\n    }\n  }\n\n  get firstLevel(): number {\n    return this._firstLevel;\n  }\n\n  set firstLevel(newLevel) {\n    this._firstLevel = newLevel;\n  }\n\n  get startLevel(): number {\n    // Setting hls.startLevel (this._startLevel) overrides config.startLevel\n    if (this._startLevel === undefined) {\n      const configStartLevel = this.hls.config.startLevel;\n      if (configStartLevel !== undefined) {\n        return configStartLevel;\n      }\n      return this.hls.firstAutoLevel;\n    }\n    return this._startLevel;\n  }\n\n  set startLevel(newLevel: number) {\n    this._startLevel = newLevel;\n  }\n\n  protected onError(event: Events.ERROR, data: ErrorData) {\n    if (data.fatal || !data.context) {\n      return;\n    }\n\n    if (\n      data.context.type === PlaylistContextType.LEVEL &&\n      data.context.level === this.level\n    ) {\n      this.checkRetry(data);\n    }\n  }\n\n  // reset errors on the successful load of a fragment\n  protected onFragBuffered(\n    event: Events.FRAG_BUFFERED,\n    { frag }: FragBufferedData,\n  ) {\n    if (frag !== undefined && frag.type === PlaylistLevelType.MAIN) {\n      const el = frag.elementaryStreams;\n      if (!Object.keys(el).some((type) => !!el[type])) {\n        return;\n      }\n      const level = this._levels[frag.level];\n      if (level?.loadError) {\n        this.log(\n          `Resetting level error count of ${level.loadError} on frag buffered`,\n        );\n        level.loadError = 0;\n      }\n    }\n  }\n\n  protected onLevelLoaded(event: Events.LEVEL_LOADED, data: LevelLoadedData) {\n    const { level, details } = data;\n    const curLevel = this._levels[level];\n\n    if (!curLevel) {\n      this.warn(`Invalid level index ${level}`);\n      if (data.deliveryDirectives?.skip) {\n        details.deltaUpdateFailed = true;\n      }\n      return;\n    }\n\n    // only process level loaded events matching with expected level\n    if (level === this.currentLevelIndex) {\n      // reset level load error counter on successful level loaded only if there is no issues with fragments\n      if (curLevel.fragmentError === 0) {\n        curLevel.loadError = 0;\n      }\n      this.playlistLoaded(level, data, curLevel.details);\n    } else if (data.deliveryDirectives?.skip) {\n      // received a delta playlist update that cannot be merged\n      details.deltaUpdateFailed = true;\n    }\n  }\n\n  protected loadPlaylist(hlsUrlParameters?: HlsUrlParameters) {\n    super.loadPlaylist();\n    const currentLevelIndex = this.currentLevelIndex;\n    const currentLevel = this.currentLevel;\n\n    if (currentLevel && this.shouldLoadPlaylist(currentLevel)) {\n      let url = currentLevel.uri;\n      if (hlsUrlParameters) {\n        try {\n          url = hlsUrlParameters.addDirectives(url);\n        } catch (error) {\n          this.warn(\n            `Could not construct new URL with HLS Delivery Directives: ${error}`,\n          );\n        }\n      }\n\n      const pathwayId = currentLevel.attrs['PATHWAY-ID'];\n      this.log(\n        `Loading level index ${currentLevelIndex}${\n          hlsUrlParameters?.msn !== undefined\n            ? ' at sn ' +\n              hlsUrlParameters.msn +\n              ' part ' +\n              hlsUrlParameters.part\n            : ''\n        } with${pathwayId ? ' Pathway ' + pathwayId : ''} ${url}`,\n      );\n\n      // console.log('Current audio track group ID:', this.hls.audioTracks[this.hls.audioTrack].groupId);\n      // console.log('New video quality level audio group id:', levelObject.attrs.AUDIO, level);\n      this.clearTimer();\n      this.hls.trigger(Events.LEVEL_LOADING, {\n        url,\n        level: currentLevelIndex,\n        pathwayId: currentLevel.attrs['PATHWAY-ID'],\n        id: 0, // Deprecated Level urlId\n        deliveryDirectives: hlsUrlParameters || null,\n      });\n    }\n  }\n\n  get nextLoadLevel() {\n    if (this.manualLevelIndex !== -1) {\n      return this.manualLevelIndex;\n    } else {\n      return this.hls.nextAutoLevel;\n    }\n  }\n\n  set nextLoadLevel(nextLevel) {\n    this.level = nextLevel;\n    if (this.manualLevelIndex === -1) {\n      this.hls.nextAutoLevel = nextLevel;\n    }\n  }\n\n  removeLevel(levelIndex: number) {\n    const levels = this._levels.filter((level, index) => {\n      if (index !== levelIndex) {\n        return true;\n      }\n      if (this.steering) {\n        this.steering.removeLevel(level);\n      }\n      if (level === this.currentLevel) {\n        this.currentLevel = null;\n        this.currentLevelIndex = -1;\n        if (level.details) {\n          level.details.fragments.forEach((f) => (f.level = -1));\n        }\n      }\n      return false;\n    });\n    reassignFragmentLevelIndexes(levels);\n    this._levels = levels;\n    if (this.currentLevelIndex > -1 && this.currentLevel?.details) {\n      this.currentLevelIndex = this.currentLevel.details.fragments[0].level;\n    }\n    this.hls.trigger(Events.LEVELS_UPDATED, { levels });\n  }\n\n  private onLevelsUpdated(\n    event: Events.LEVELS_UPDATED,\n    { levels }: LevelsUpdatedData,\n  ) {\n    this._levels = levels;\n  }\n\n  public checkMaxAutoUpdated() {\n    const { autoLevelCapping, maxAutoLevel, maxHdcpLevel } = this.hls;\n    if (this._maxAutoLevel !== maxAutoLevel) {\n      this._maxAutoLevel = maxAutoLevel;\n      this.hls.trigger(Events.MAX_AUTO_LEVEL_UPDATED, {\n        autoLevelCapping,\n        levels: this.levels,\n        maxAutoLevel,\n        minAutoLevel: this.hls.minAutoLevel,\n        maxHdcpLevel,\n      });\n    }\n  }\n}\n\nfunction assignTrackIdsByGroup(tracks: MediaPlaylist[]): void {\n  const groups = {};\n  tracks.forEach((track) => {\n    const groupId = track.groupId || '';\n    track.id = groups[groupId] = groups[groupId] || 0;\n    groups[groupId]++;\n  });\n}\n", "import { ErrorTypes, ErrorDetails } from '../errors';\nimport {\n  LoaderStats,\n  LoaderResponse,\n  LoaderConfiguration,\n  LoaderCallbacks,\n  Loader,\n  KeyLoaderContext,\n  PlaylistLevelType,\n} from '../types/loader';\nimport { LoadError } from './fragment-loader';\nimport type { HlsConfig } from '../config';\nimport type { Fragment } from '../loader/fragment';\nimport type { ComponentAPI } from '../types/component-api';\nimport type { KeyLoadedData } from '../types/events';\nimport type { LevelKey } from './level-key';\nimport type EMEController from '../controller/eme-controller';\nimport type { MediaKeySessionContext } from '../controller/eme-controller';\nimport type { KeySystemFormats } from '../utils/mediakeys-helper';\n\nexport interface KeyLoaderInfo {\n  decryptdata: LevelKey;\n  keyLoadPromise: Promise<KeyLoadedData> | null;\n  loader: Loader<KeyLoaderContext> | null;\n  mediaKeySessionContext: MediaKeySessionContext | null;\n}\nexport default class KeyLoader implements ComponentAPI {\n  private readonly config: HlsConfig;\n  public keyUriToKeyInfo: { [keyuri: string]: KeyLoaderInfo } = {};\n  public emeController: EMEController | null = null;\n\n  constructor(config: HlsConfig) {\n    this.config = config;\n  }\n\n  abort(type?: PlaylistLevelType) {\n    for (const uri in this.keyUriToKeyInfo) {\n      const loader = this.keyUriToKeyInfo[uri].loader;\n      if (loader) {\n        if (type && type !== loader.context?.frag.type) {\n          return;\n        }\n        loader.abort();\n      }\n    }\n  }\n\n  detach() {\n    for (const uri in this.keyUriToKeyInfo) {\n      const keyInfo = this.keyUriToKeyInfo[uri];\n      // Remove cached EME keys on detach\n      if (\n        keyInfo.mediaKeySessionContext ||\n        keyInfo.decryptdata.isCommonEncryption\n      ) {\n        delete this.keyUriToKeyInfo[uri];\n      }\n    }\n  }\n\n  destroy() {\n    this.detach();\n    for (const uri in this.keyUriToKeyInfo) {\n      const loader = this.keyUriToKeyInfo[uri].loader;\n      if (loader) {\n        loader.destroy();\n      }\n    }\n    this.keyUriToKeyInfo = {};\n  }\n\n  createKeyLoadError(\n    frag: Fragment,\n    details: ErrorDetails = ErrorDetails.KEY_LOAD_ERROR,\n    error: Error,\n    networkDetails?: any,\n    response?: { url: string; data: undefined; code: number; text: string },\n  ): LoadError {\n    return new LoadError({\n      type: ErrorTypes.NETWORK_ERROR,\n      details,\n      fatal: false,\n      frag,\n      response,\n      error,\n      networkDetails,\n    });\n  }\n\n  loadClear(\n    loadingFrag: Fragment,\n    encryptedFragments: Fragment[],\n  ): void | Promise<void> {\n    if (this.emeController && this.config.emeEnabled) {\n      // access key-system with nearest key on start (loaidng frag is unencrypted)\n      const { sn, cc } = loadingFrag;\n      for (let i = 0; i < encryptedFragments.length; i++) {\n        const frag = encryptedFragments[i];\n        if (\n          cc <= frag.cc &&\n          (sn === 'initSegment' || frag.sn === 'initSegment' || sn < frag.sn)\n        ) {\n          this.emeController\n            .selectKeySystemFormat(frag)\n            .then((keySystemFormat) => {\n              frag.setKeyFormat(keySystemFormat);\n            });\n          break;\n        }\n      }\n    }\n  }\n\n  load(frag: Fragment): Promise<KeyLoadedData> {\n    if (!frag.decryptdata && frag.encrypted && this.emeController) {\n      // Multiple keys, but none selected, resolve in eme-controller\n      return this.emeController\n        .selectKeySystemFormat(frag)\n        .then((keySystemFormat) => {\n          return this.loadInternal(frag, keySystemFormat);\n        });\n    }\n\n    return this.loadInternal(frag);\n  }\n\n  loadInternal(\n    frag: Fragment,\n    keySystemFormat?: KeySystemFormats,\n  ): Promise<KeyLoadedData> {\n    if (keySystemFormat) {\n      frag.setKeyFormat(keySystemFormat);\n    }\n    const decryptdata = frag.decryptdata;\n    if (!decryptdata) {\n      const error = new Error(\n        keySystemFormat\n          ? `Expected frag.decryptdata to be defined after setting format ${keySystemFormat}`\n          : 'Missing decryption data on fragment in onKeyLoading',\n      );\n      return Promise.reject(\n        this.createKeyLoadError(frag, ErrorDetails.KEY_LOAD_ERROR, error),\n      );\n    }\n    const uri = decryptdata.uri;\n    if (!uri) {\n      return Promise.reject(\n        this.createKeyLoadError(\n          frag,\n          ErrorDetails.KEY_LOAD_ERROR,\n          new Error(`Invalid key URI: \"${uri}\"`),\n        ),\n      );\n    }\n    let keyInfo = this.keyUriToKeyInfo[uri];\n\n    if (keyInfo?.decryptdata.key) {\n      decryptdata.key = keyInfo.decryptdata.key;\n      return Promise.resolve({ frag, keyInfo });\n    }\n    // Return key load promise as long as it does not have a mediakey session with an unusable key status\n    if (keyInfo?.keyLoadPromise) {\n      switch (keyInfo.mediaKeySessionContext?.keyStatus) {\n        case undefined:\n        case 'status-pending':\n        case 'usable':\n        case 'usable-in-future':\n          return keyInfo.keyLoadPromise.then((keyLoadedData) => {\n            // Return the correct fragment with updated decryptdata key and loaded keyInfo\n            decryptdata.key = keyLoadedData.keyInfo.decryptdata.key;\n            return { frag, keyInfo };\n          });\n      }\n      // If we have a key session and status and it is not pending or usable, continue\n      // This will go back to the eme-controller for expired keys to get a new keyLoadPromise\n    }\n\n    // Load the key or return the loading promise\n    keyInfo = this.keyUriToKeyInfo[uri] = {\n      decryptdata,\n      keyLoadPromise: null,\n      loader: null,\n      mediaKeySessionContext: null,\n    };\n\n    switch (decryptdata.method) {\n      case 'ISO-23001-7':\n      case 'SAMPLE-AES':\n      case 'SAMPLE-AES-CENC':\n      case 'SAMPLE-AES-CTR':\n        if (decryptdata.keyFormat === 'identity') {\n          // loadKeyHTTP handles http(s) and data URLs\n          return this.loadKeyHTTP(keyInfo, frag);\n        }\n        return this.loadKeyEME(keyInfo, frag);\n      case 'AES-128':\n        return this.loadKeyHTTP(keyInfo, frag);\n      default:\n        return Promise.reject(\n          this.createKeyLoadError(\n            frag,\n            ErrorDetails.KEY_LOAD_ERROR,\n            new Error(\n              `Key supplied with unsupported METHOD: \"${decryptdata.method}\"`,\n            ),\n          ),\n        );\n    }\n  }\n\n  loadKeyEME(keyInfo: KeyLoaderInfo, frag: Fragment): Promise<KeyLoadedData> {\n    const keyLoadedData: KeyLoadedData = { frag, keyInfo };\n    if (this.emeController && this.config.emeEnabled) {\n      const keySessionContextPromise =\n        this.emeController.loadKey(keyLoadedData);\n      if (keySessionContextPromise) {\n        return (keyInfo.keyLoadPromise = keySessionContextPromise.then(\n          (keySessionContext) => {\n            keyInfo.mediaKeySessionContext = keySessionContext;\n            return keyLoadedData;\n          },\n        )).catch((error) => {\n          // Remove promise for license renewal or retry\n          keyInfo.keyLoadPromise = null;\n          throw error;\n        });\n      }\n    }\n    return Promise.resolve(keyLoadedData);\n  }\n\n  loadKeyHTTP(keyInfo: KeyLoaderInfo, frag: Fragment): Promise<KeyLoadedData> {\n    const config = this.config;\n    const Loader = config.loader;\n    const keyLoader = new Loader(config) as Loader<KeyLoaderContext>;\n    frag.keyLoader = keyInfo.loader = keyLoader;\n\n    return (keyInfo.keyLoadPromise = new Promise((resolve, reject) => {\n      const loaderContext: KeyLoaderContext = {\n        keyInfo,\n        frag,\n        responseType: 'arraybuffer',\n        url: keyInfo.decryptdata.uri,\n      };\n\n      // maxRetry is 0 so that instead of retrying the same key on the same variant multiple times,\n      // key-loader will trigger an error and rely on stream-controller to handle retry logic.\n      // this will also align retry logic with fragment-loader\n      const loadPolicy = config.keyLoadPolicy.default;\n      const loaderConfig: LoaderConfiguration = {\n        loadPolicy,\n        timeout: loadPolicy.maxLoadTimeMs,\n        maxRetry: 0,\n        retryDelay: 0,\n        maxRetryDelay: 0,\n      };\n\n      const loaderCallbacks: LoaderCallbacks<KeyLoaderContext> = {\n        onSuccess: (\n          response: LoaderResponse,\n          stats: LoaderStats,\n          context: KeyLoaderContext,\n          networkDetails: any,\n        ) => {\n          const { frag, keyInfo, url: uri } = context;\n          if (!frag.decryptdata || keyInfo !== this.keyUriToKeyInfo[uri]) {\n            return reject(\n              this.createKeyLoadError(\n                frag,\n                ErrorDetails.KEY_LOAD_ERROR,\n                new Error('after key load, decryptdata unset or changed'),\n                networkDetails,\n              ),\n            );\n          }\n\n          keyInfo.decryptdata.key = frag.decryptdata.key = new Uint8Array(\n            response.data as ArrayBuffer,\n          );\n\n          // detach fragment key loader on load success\n          frag.keyLoader = null;\n          keyInfo.loader = null;\n          resolve({ frag, keyInfo });\n        },\n\n        onError: (\n          response: { code: number; text: string },\n          context: KeyLoaderContext,\n          networkDetails: any,\n          stats: LoaderStats,\n        ) => {\n          this.resetLoader(context);\n          reject(\n            this.createKeyLoadError(\n              frag,\n              ErrorDetails.KEY_LOAD_ERROR,\n              new Error(\n                `HTTP Error ${response.code} loading key ${response.text}`,\n              ),\n              networkDetails,\n              { url: loaderContext.url, data: undefined, ...response },\n            ),\n          );\n        },\n\n        onTimeout: (\n          stats: LoaderStats,\n          context: KeyLoaderContext,\n          networkDetails: any,\n        ) => {\n          this.resetLoader(context);\n          reject(\n            this.createKeyLoadError(\n              frag,\n              ErrorDetails.KEY_LOAD_TIMEOUT,\n              new Error('key loading timed out'),\n              networkDetails,\n            ),\n          );\n        },\n\n        onAbort: (\n          stats: LoaderStats,\n          context: KeyLoaderContext,\n          networkDetails: any,\n        ) => {\n          this.resetLoader(context);\n          reject(\n            this.createKeyLoadError(\n              frag,\n              ErrorDetails.INTERNAL_ABORTED,\n              new Error('key loading aborted'),\n              networkDetails,\n            ),\n          );\n        },\n      };\n\n      keyLoader.load(loaderContext, loaderConfig, loaderCallbacks);\n    }));\n  }\n\n  private resetLoader(context: KeyLoaderContext) {\n    const { frag, keyInfo, url: uri } = context;\n    const loader = keyInfo.loader;\n    if (frag.keyLoader === loader) {\n      frag.keyLoader = null;\n      keyInfo.loader = null;\n    }\n    delete this.keyUriToKeyInfo[uri];\n    if (loader) {\n      loader.destroy();\n    }\n  }\n}\n", "import { getMediaSource } from './utils/mediasource-helper';\nimport { mimeTypeForCodec } from './utils/codecs';\nimport type { ExtendedSourceBuffer } from './types/buffer';\n\nfunction getSourceBuffer(): typeof self.SourceBuffer {\n  return self.SourceBuffer || (self as any).WebKitSourceBuffer;\n}\n\nexport function isMSESupported(): boolean {\n  const mediaSource = getMediaSource();\n  if (!mediaSource) {\n    return false;\n  }\n\n  // if SourceBuffer is exposed ensure its API is valid\n  // Older browsers do not expose SourceBuffer globally so checking SourceBuffer.prototype is impossible\n  const sourceBuffer = getSourceBuffer();\n  return (\n    !sourceBuffer ||\n    (sourceBuffer.prototype &&\n      typeof sourceBuffer.prototype.appendBuffer === 'function' &&\n      typeof sourceBuffer.prototype.remove === 'function')\n  );\n}\n\nexport function isSupported(): boolean {\n  if (!isMSESupported()) {\n    return false;\n  }\n\n  const mediaSource = getMediaSource();\n  return (\n    typeof mediaSource?.isTypeSupported === 'function' &&\n    (['avc1.42E01E,mp4a.40.2', 'av01.0.01M.08', 'vp09.00.50.08'].some(\n      (codecsForVideoContainer) =>\n        mediaSource.isTypeSupported(\n          mimeTypeForCodec(codecsForVideoContainer, 'video'),\n        ),\n    ) ||\n      ['mp4a.40.2', 'fLaC'].some((codecForAudioContainer) =>\n        mediaSource.isTypeSupported(\n          mimeTypeForCodec(codecForAudioContainer, 'audio'),\n        ),\n      ))\n  );\n}\n\nexport function changeTypeSupported(): boolean {\n  const sourceBuffer = getSourceBuffer();\n  return (\n    typeof (sourceBuffer?.prototype as ExtendedSourceBuffer)?.changeType ===\n    'function'\n  );\n}\n", "import type { BufferInfo } from '../utils/buffer-helper';\nimport { BufferHelper } from '../utils/buffer-helper';\nimport { ErrorTypes, ErrorDetails } from '../errors';\nimport { PlaylistLevelType } from '../types/loader';\nimport { Events } from '../events';\nimport { logger } from '../utils/logger';\nimport type Hls from '../hls';\nimport type { HlsConfig } from '../config';\nimport type { Fragment } from '../loader/fragment';\nimport type { FragmentTracker } from './fragment-tracker';\n\nexport const STALL_MINIMUM_DURATION_MS = 250;\nexport const MAX_START_GAP_JUMP = 2.0;\nexport const SKIP_BUFFER_HOLE_STEP_SECONDS = 0.1;\nexport const SKIP_BUFFER_RANGE_START = 0.05;\n\nexport default class GapController {\n  private config: HlsConfig;\n  private media: HTMLMediaElement | null = null;\n  private fragmentTracker: FragmentTracker;\n  private hls: Hls;\n  private nudgeRetry: number = 0;\n  private stallReported: boolean = false;\n  private stalled: number | null = null;\n  private moved: boolean = false;\n  private seeking: boolean = false;\n\n  constructor(config, media, fragmentTracker, hls) {\n    this.config = config;\n    this.media = media;\n    this.fragmentTracker = fragmentTracker;\n    this.hls = hls;\n  }\n\n  public destroy() {\n    this.media = null;\n    // @ts-ignore\n    this.hls = this.fragmentTracker = null;\n  }\n\n  /**\n   * Checks if the playhead is stuck within a gap, and if so, attempts to free it.\n   * A gap is an unbuffered range between two buffered ranges (or the start and the first buffered range).\n   *\n   * @param lastCurrentTime - Previously read playhead position\n   */\n  public poll(lastCurrentTime: number, activeFrag: Fragment | null) {\n    const { config, media, stalled } = this;\n    if (media === null) {\n      return;\n    }\n    const { currentTime, seeking } = media;\n    const seeked = this.seeking && !seeking;\n    const beginSeek = !this.seeking && seeking;\n\n    this.seeking = seeking;\n\n    // The playhead is moving, no-op\n    if (currentTime !== lastCurrentTime) {\n      this.moved = true;\n      if (!seeking) {\n        this.nudgeRetry = 0;\n      }\n      if (stalled !== null) {\n        // The playhead is now moving, but was previously stalled\n        if (this.stallReported) {\n          const stalledDuration = self.performance.now() - stalled;\n          logger.warn(\n            `playback not stuck anymore @${currentTime}, after ${Math.round(\n              stalledDuration,\n            )}ms`,\n          );\n          this.stallReported = false;\n        }\n        this.stalled = null;\n      }\n      return;\n    }\n\n    // Clear stalled state when beginning or finishing seeking so that we don't report stalls coming out of a seek\n    if (beginSeek || seeked) {\n      this.stalled = null;\n      return;\n    }\n\n    // The playhead should not be moving\n    if (\n      (media.paused && !seeking) ||\n      media.ended ||\n      media.playbackRate === 0 ||\n      !BufferHelper.getBuffered(media).length\n    ) {\n      this.nudgeRetry = 0;\n      return;\n    }\n\n    const bufferInfo = BufferHelper.bufferInfo(media, currentTime, 0);\n    const nextStart = bufferInfo.nextStart || 0;\n\n    if (seeking) {\n      // Waiting for seeking in a buffered range to complete\n      const hasEnoughBuffer = bufferInfo.len > MAX_START_GAP_JUMP;\n      // Next buffered range is too far ahead to jump to while still seeking\n      const noBufferGap =\n        !nextStart ||\n        (activeFrag && activeFrag.start <= currentTime) ||\n        (nextStart - currentTime > MAX_START_GAP_JUMP &&\n          !this.fragmentTracker.getPartialFragment(currentTime));\n      if (hasEnoughBuffer || noBufferGap) {\n        return;\n      }\n      // Reset moved state when seeking to a point in or before a gap\n      this.moved = false;\n    }\n\n    // Skip start gaps if we haven't played, but the last poll detected the start of a stall\n    // The addition poll gives the browser a chance to jump the gap for us\n    if (!this.moved && this.stalled !== null) {\n      // There is no playable buffer (seeked, waiting for buffer)\n      const isBuffered = bufferInfo.len > 0;\n      if (!isBuffered && !nextStart) {\n        return;\n      }\n      // Jump start gaps within jump threshold\n      const startJump =\n        Math.max(nextStart, bufferInfo.start || 0) - currentTime;\n\n      // When joining a live stream with audio tracks, account for live playlist window sliding by allowing\n      // a larger jump over start gaps caused by the audio-stream-controller buffering a start fragment\n      // that begins over 1 target duration after the video start position.\n      const level = this.hls.levels\n        ? this.hls.levels[this.hls.currentLevel]\n        : null;\n      const isLive = level?.details?.live;\n      const maxStartGapJump = isLive\n        ? level!.details!.targetduration * 2\n        : MAX_START_GAP_JUMP;\n      const partialOrGap = this.fragmentTracker.getPartialFragment(currentTime);\n      if (startJump > 0 && (startJump <= maxStartGapJump || partialOrGap)) {\n        if (!media.paused) {\n          this._trySkipBufferHole(partialOrGap);\n        }\n        return;\n      }\n    }\n\n    // Start tracking stall time\n    const tnow = self.performance.now();\n    if (stalled === null) {\n      this.stalled = tnow;\n      return;\n    }\n\n    const stalledDuration = tnow - stalled;\n    if (!seeking && stalledDuration >= STALL_MINIMUM_DURATION_MS) {\n      // Report stalling after trying to fix\n      this._reportStall(bufferInfo);\n      if (!this.media) {\n        return;\n      }\n    }\n\n    const bufferedWithHoles = BufferHelper.bufferInfo(\n      media,\n      currentTime,\n      config.maxBufferHole,\n    );\n    this._tryFixBufferStall(bufferedWithHoles, stalledDuration);\n  }\n\n  /**\n   * Detects and attempts to fix known buffer stalling issues.\n   * @param bufferInfo - The properties of the current buffer.\n   * @param stalledDurationMs - The amount of time Hls.js has been stalling for.\n   * @private\n   */\n  private _tryFixBufferStall(\n    bufferInfo: BufferInfo,\n    stalledDurationMs: number,\n  ) {\n    const { config, fragmentTracker, media } = this;\n    if (media === null) {\n      return;\n    }\n    const currentTime = media.currentTime;\n\n    const partial = fragmentTracker.getPartialFragment(currentTime);\n    if (partial) {\n      // Try to skip over the buffer hole caused by a partial fragment\n      // This method isn't limited by the size of the gap between buffered ranges\n      const targetTime = this._trySkipBufferHole(partial);\n      // we return here in this case, meaning\n      // the branch below only executes when we haven't seeked to a new position\n      if (targetTime || !this.media) {\n        return;\n      }\n    }\n\n    // if we haven't had to skip over a buffer hole of a partial fragment\n    // we may just have to \"nudge\" the playlist as the browser decoding/rendering engine\n    // needs to cross some sort of threshold covering all source-buffers content\n    // to start playing properly.\n    if (\n      (bufferInfo.len > config.maxBufferHole ||\n        (bufferInfo.nextStart &&\n          bufferInfo.nextStart - currentTime < config.maxBufferHole)) &&\n      stalledDurationMs > config.highBufferWatchdogPeriod * 1000\n    ) {\n      logger.warn('Trying to nudge playhead over buffer-hole');\n      // Try to nudge currentTime over a buffer hole if we've been stalling for the configured amount of seconds\n      // We only try to jump the hole if it's under the configured size\n      // Reset stalled so to rearm watchdog timer\n      this.stalled = null;\n      this._tryNudgeBuffer();\n    }\n  }\n\n  /**\n   * Triggers a BUFFER_STALLED_ERROR event, but only once per stall period.\n   * @param bufferLen - The playhead distance from the end of the current buffer segment.\n   * @private\n   */\n  private _reportStall(bufferInfo: BufferInfo) {\n    const { hls, media, stallReported } = this;\n    if (!stallReported && media) {\n      // Report stalled error once\n      this.stallReported = true;\n      const error = new Error(\n        `Playback stalling at @${\n          media.currentTime\n        } due to low buffer (${JSON.stringify(bufferInfo)})`,\n      );\n      logger.warn(error.message);\n      hls.trigger(Events.ERROR, {\n        type: ErrorTypes.MEDIA_ERROR,\n        details: ErrorDetails.BUFFER_STALLED_ERROR,\n        fatal: false,\n        error,\n        buffer: bufferInfo.len,\n      });\n    }\n  }\n\n  /**\n   * Attempts to fix buffer stalls by jumping over known gaps caused by partial fragments\n   * @param partial - The partial fragment found at the current time (where playback is stalling).\n   * @private\n   */\n  private _trySkipBufferHole(partial: Fragment | null): number {\n    const { config, hls, media } = this;\n    if (media === null) {\n      return 0;\n    }\n\n    // Check if currentTime is between unbuffered regions of partial fragments\n    const currentTime = media.currentTime;\n    const bufferInfo = BufferHelper.bufferInfo(media, currentTime, 0);\n    const startTime =\n      currentTime < bufferInfo.start ? bufferInfo.start : bufferInfo.nextStart;\n    if (startTime) {\n      const bufferStarved = bufferInfo.len <= config.maxBufferHole;\n      const waiting =\n        bufferInfo.len > 0 && bufferInfo.len < 1 && media.readyState < 3;\n      const gapLength = startTime - currentTime;\n      if (gapLength > 0 && (bufferStarved || waiting)) {\n        // Only allow large gaps to be skipped if it is a start gap, or all fragments in skip range are partial\n        if (gapLength > config.maxBufferHole) {\n          const { fragmentTracker } = this;\n          let startGap = false;\n          if (currentTime === 0) {\n            const startFrag = fragmentTracker.getAppendedFrag(\n              0,\n              PlaylistLevelType.MAIN,\n            );\n            if (startFrag && startTime < startFrag.end) {\n              startGap = true;\n            }\n          }\n          if (!startGap) {\n            const startProvisioned =\n              partial ||\n              fragmentTracker.getAppendedFrag(\n                currentTime,\n                PlaylistLevelType.MAIN,\n              );\n            if (startProvisioned) {\n              let moreToLoad = false;\n              let pos = startProvisioned.end;\n              while (pos < startTime) {\n                const provisioned = fragmentTracker.getPartialFragment(pos);\n                if (provisioned) {\n                  pos += provisioned.duration;\n                } else {\n                  moreToLoad = true;\n                  break;\n                }\n              }\n              if (moreToLoad) {\n                return 0;\n              }\n            }\n          }\n        }\n        const targetTime = Math.max(\n          startTime + SKIP_BUFFER_RANGE_START,\n          currentTime + SKIP_BUFFER_HOLE_STEP_SECONDS,\n        );\n        logger.warn(\n          `skipping hole, adjusting currentTime from ${currentTime} to ${targetTime}`,\n        );\n        this.moved = true;\n        this.stalled = null;\n        media.currentTime = targetTime;\n        if (partial && !partial.gap) {\n          const error = new Error(\n            `fragment loaded with buffer holes, seeking from ${currentTime} to ${targetTime}`,\n          );\n          hls.trigger(Events.ERROR, {\n            type: ErrorTypes.MEDIA_ERROR,\n            details: ErrorDetails.BUFFER_SEEK_OVER_HOLE,\n            fatal: false,\n            error,\n            reason: error.message,\n            frag: partial,\n          });\n        }\n        return targetTime;\n      }\n    }\n    return 0;\n  }\n\n  /**\n   * Attempts to fix buffer stalls by advancing the mediaElement's current time by a small amount.\n   * @private\n   */\n  private _tryNudgeBuffer() {\n    const { config, hls, media, nudgeRetry } = this;\n    if (media === null) {\n      return;\n    }\n    const currentTime = media.currentTime;\n    this.nudgeRetry++;\n\n    if (nudgeRetry < config.nudgeMaxRetry) {\n      const targetTime = currentTime + (nudgeRetry + 1) * config.nudgeOffset;\n      // playback stalled in buffered area ... let's nudge currentTime to try to overcome this\n      const error = new Error(\n        `Nudging 'currentTime' from ${currentTime} to ${targetTime}`,\n      );\n      logger.warn(error.message);\n      media.currentTime = targetTime;\n      hls.trigger(Events.ERROR, {\n        type: ErrorTypes.MEDIA_ERROR,\n        details: ErrorDetails.BUFFER_NUDGE_ON_STALL,\n        error,\n        fatal: false,\n      });\n    } else {\n      const error = new Error(\n        `Playhead still not moving while enough data buffered @${currentTime} after ${config.nudgeMaxRetry} nudges`,\n      );\n      logger.error(error.message);\n      hls.trigger(Events.ERROR, {\n        type: ErrorTypes.MEDIA_ERROR,\n        details: ErrorDetails.BUFFER_STALLED_ERROR,\n        error,\n        fatal: true,\n      });\n    }\n  }\n}\n", "import BaseStreamController, { State } from './base-stream-controller';\nimport { changeTypeSupported } from '../is-supported';\nimport { Events } from '../events';\nimport { BufferHelper, BufferInfo } from '../utils/buffer-helper';\nimport { FragmentState } from './fragment-tracker';\nimport { PlaylistContextType, PlaylistLevelType } from '../types/loader';\nimport { ElementaryStreamTypes, Fragment } from '../loader/fragment';\nimport TransmuxerInterface from '../demux/transmuxer-interface';\nimport { ChunkMetadata } from '../types/transmuxer';\nimport GapController, { MAX_START_GAP_JUMP } from './gap-controller';\nimport { ErrorDetails } from '../errors';\nimport type { NetworkComponentAPI } from '../types/component-api';\nimport type Hls from '../hls';\nimport type { Level } from '../types/level';\nimport type { LevelDetails } from '../loader/level-details';\nimport type { FragmentTracker } from './fragment-tracker';\nimport type KeyLoader from '../loader/key-loader';\nimport type { TransmuxerResult } from '../types/transmuxer';\nimport type { TrackSet } from '../types/track';\nimport type { SourceBufferName } from '../types/buffer';\nimport type {\n  AudioTrackSwitchedData,\n  AudioTrackSwitchingData,\n  BufferCreatedData,\n  BufferEOSData,\n  BufferFlushedData,\n  ErrorData,\n  FragBufferedData,\n  FragLoadedData,\n  FragParsingMetadataData,\n  FragParsingUserdataData,\n  LevelLoadedData,\n  LevelLoadingData,\n  LevelsUpdatedData,\n  ManifestParsedData,\n  MediaAttachedData,\n} from '../types/events';\n\nconst TICK_INTERVAL = 100; // how often to tick in ms\n\nexport default class StreamController\n  extends BaseStreamController\n  implements NetworkComponentAPI\n{\n  private audioCodecSwap: boolean = false;\n  private gapController: GapController | null = null;\n  private level: number = -1;\n  private _forceStartLoad: boolean = false;\n  private altAudio: boolean = false;\n  private audioOnly: boolean = false;\n  private fragPlaying: Fragment | null = null;\n  private onvplaying: EventListener | null = null;\n  private onvseeked: EventListener | null = null;\n  private fragLastKbps: number = 0;\n  private couldBacktrack: boolean = false;\n  private backtrackFragment: Fragment | null = null;\n  private audioCodecSwitch: boolean = false;\n  private videoBuffer: any | null = null;\n\n  constructor(\n    hls: Hls,\n    fragmentTracker: FragmentTracker,\n    keyLoader: KeyLoader,\n  ) {\n    super(\n      hls,\n      fragmentTracker,\n      keyLoader,\n      '[stream-controller]',\n      PlaylistLevelType.MAIN,\n    );\n    this._registerListeners();\n  }\n\n  private _registerListeners() {\n    const { hls } = this;\n    hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n    hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n    hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    hls.on(Events.MANIFEST_PARSED, this.onManifestParsed, this);\n    hls.on(Events.LEVEL_LOADING, this.onLevelLoading, this);\n    hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);\n    hls.on(\n      Events.FRAG_LOAD_EMERGENCY_ABORTED,\n      this.onFragLoadEmergencyAborted,\n      this,\n    );\n    hls.on(Events.ERROR, this.onError, this);\n    hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);\n    hls.on(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);\n    hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);\n    hls.on(Events.BUFFER_FLUSHED, this.onBufferFlushed, this);\n    hls.on(Events.LEVELS_UPDATED, this.onLevelsUpdated, this);\n    hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);\n  }\n\n  protected _unregisterListeners() {\n    const { hls } = this;\n    hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n    hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n    hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n    hls.off(Events.MANIFEST_PARSED, this.onManifestParsed, this);\n    hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);\n    hls.off(\n      Events.FRAG_LOAD_EMERGENCY_ABORTED,\n      this.onFragLoadEmergencyAborted,\n      this,\n    );\n    hls.off(Events.ERROR, this.onError, this);\n    hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);\n    hls.off(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);\n    hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);\n    hls.off(Events.BUFFER_FLUSHED, this.onBufferFlushed, this);\n    hls.off(Events.LEVELS_UPDATED, this.onLevelsUpdated, this);\n    hls.off(Events.FRAG_BUFFERED, this.onFragBuffered, this);\n  }\n\n  protected onHandlerDestroying() {\n    this._unregisterListeners();\n    super.onHandlerDestroying();\n  }\n\n  public startLoad(startPosition: number): void {\n    if (this.levels) {\n      const { lastCurrentTime, hls } = this;\n      this.stopLoad();\n      this.setInterval(TICK_INTERVAL);\n      this.level = -1;\n      if (!this.startFragRequested) {\n        // determine load level\n        let startLevel = hls.startLevel;\n        if (startLevel === -1) {\n          if (hls.config.testBandwidth && this.levels.length > 1) {\n            // -1 : guess start Level by doing a bitrate test by loading first fragment of lowest quality level\n            startLevel = 0;\n            this.bitrateTest = true;\n          } else {\n            startLevel = hls.firstAutoLevel;\n          }\n        }\n        // set new level to playlist loader : this will trigger start level load\n        // hls.nextLoadLevel remains until it is set to a new value or until a new frag is successfully loaded\n        hls.nextLoadLevel = startLevel;\n        this.level = hls.loadLevel;\n        this.loadedmetadata = false;\n      }\n      // if startPosition undefined but lastCurrentTime set, set startPosition to last currentTime\n      if (lastCurrentTime > 0 && startPosition === -1) {\n        this.log(\n          `Override startPosition with lastCurrentTime @${lastCurrentTime.toFixed(\n            3,\n          )}`,\n        );\n        startPosition = lastCurrentTime;\n      }\n      this.state = State.IDLE;\n      this.nextLoadPosition =\n        this.startPosition =\n        this.lastCurrentTime =\n          startPosition;\n      this.tick();\n    } else {\n      this._forceStartLoad = true;\n      this.state = State.STOPPED;\n    }\n  }\n\n  public stopLoad() {\n    this._forceStartLoad = false;\n    super.stopLoad();\n  }\n\n  protected doTick() {\n    switch (this.state) {\n      case State.WAITING_LEVEL: {\n        const { levels, level } = this;\n        const currentLevel = levels?.[level];\n        const details = currentLevel?.details;\n        if (\n          details &&\n          (!details.live || this.levelLastLoaded === currentLevel)\n        ) {\n          if (this.waitForCdnTuneIn(details)) {\n            break;\n          }\n          this.state = State.IDLE;\n          break;\n        } else if (this.hls.nextLoadLevel !== this.level) {\n          this.state = State.IDLE;\n          break;\n        }\n        break;\n      }\n      case State.FRAG_LOADING_WAITING_RETRY:\n        {\n          const now = self.performance.now();\n          const retryDate = this.retryDate;\n          // if current time is gt than retryDate, or if media seeking let's switch to IDLE state to retry loading\n          if (!retryDate || now >= retryDate || this.media?.seeking) {\n            const { levels, level } = this;\n            const currentLevel = levels?.[level];\n            this.resetStartWhenNotLoaded(currentLevel || null);\n            this.state = State.IDLE;\n          }\n        }\n        break;\n      default:\n        break;\n    }\n    if (this.state === State.IDLE) {\n      this.doTickIdle();\n    }\n    this.onTickEnd();\n  }\n\n  protected onTickEnd() {\n    super.onTickEnd();\n    this.checkBuffer();\n    this.checkFragmentChanged();\n  }\n\n  private doTickIdle() {\n    const { hls, levelLastLoaded, levels, media } = this;\n\n    // if start level not parsed yet OR\n    // if video not attached AND start fragment already requested OR start frag prefetch not enabled\n    // exit loop, as we either need more info (level not parsed) or we need media to be attached to load new fragment\n    if (\n      levelLastLoaded === null ||\n      (!media && (this.startFragRequested || !hls.config.startFragPrefetch))\n    ) {\n      return;\n    }\n\n    // If the \"main\" level is audio-only but we are loading an alternate track in the same group, do not load anything\n    if (this.altAudio && this.audioOnly) {\n      return;\n    }\n\n    const level = hls.nextLoadLevel;\n    if (!levels?.[level]) {\n      return;\n    }\n\n    const levelInfo = levels[level];\n\n    // if buffer length is less than maxBufLen try to load a new fragment\n\n    const bufferInfo = this.getMainFwdBufferInfo();\n    if (bufferInfo === null) {\n      return;\n    }\n\n    const lastDetails = this.getLevelDetails();\n    if (lastDetails && this._streamEnded(bufferInfo, lastDetails)) {\n      const data: BufferEOSData = {};\n      if (this.altAudio) {\n        data.type = 'video';\n      }\n\n      this.hls.trigger(Events.BUFFER_EOS, data);\n      this.state = State.ENDED;\n      return;\n    }\n\n    // set next load level : this will trigger a playlist load if needed\n    if (hls.loadLevel !== level && hls.manualLevel === -1) {\n      this.log(`Adapting to level ${level} from level ${this.level}`);\n    }\n    this.level = hls.nextLoadLevel = level;\n\n    const levelDetails = levelInfo.details;\n    // if level info not retrieved yet, switch state and wait for level retrieval\n    // if live playlist, ensure that new playlist has been refreshed to avoid loading/try to load\n    // a useless and outdated fragment (that might even introduce load error if it is already out of the live playlist)\n    if (\n      !levelDetails ||\n      this.state === State.WAITING_LEVEL ||\n      (levelDetails.live && this.levelLastLoaded !== levelInfo)\n    ) {\n      this.level = level;\n      this.state = State.WAITING_LEVEL;\n      return;\n    }\n\n    const bufferLen = bufferInfo.len;\n\n    // compute max Buffer Length that we could get from this load level, based on level bitrate. don't buffer more than 60 MB and more than 30s\n    const maxBufLen = this.getMaxBufferLength(levelInfo.maxBitrate);\n\n    // Stay idle if we are still with buffer margins\n    if (bufferLen >= maxBufLen) {\n      return;\n    }\n\n    if (\n      this.backtrackFragment &&\n      this.backtrackFragment.start > bufferInfo.end\n    ) {\n      this.backtrackFragment = null;\n    }\n    const targetBufferTime = this.backtrackFragment\n      ? this.backtrackFragment.start\n      : bufferInfo.end;\n    let frag = this.getNextFragment(targetBufferTime, levelDetails);\n    // Avoid backtracking by loading an earlier segment in streams with segments that do not start with a key frame (flagged by `couldBacktrack`)\n    if (\n      this.couldBacktrack &&\n      !this.fragPrevious &&\n      frag &&\n      frag.sn !== 'initSegment' &&\n      this.fragmentTracker.getState(frag) !== FragmentState.OK\n    ) {\n      const backtrackSn = (this.backtrackFragment ?? frag).sn as number;\n      const fragIdx = backtrackSn - levelDetails.startSN;\n      const backtrackFrag = levelDetails.fragments[fragIdx - 1];\n      if (backtrackFrag && frag.cc === backtrackFrag.cc) {\n        frag = backtrackFrag;\n        this.fragmentTracker.removeFragment(backtrackFrag);\n      }\n    } else if (this.backtrackFragment && bufferInfo.len) {\n      this.backtrackFragment = null;\n    }\n    // Avoid loop loading by using nextLoadPosition set for backtracking and skipping consecutive GAP tags\n    if (frag && this.isLoopLoading(frag, targetBufferTime)) {\n      const gapStart = frag.gap;\n      if (!gapStart) {\n        // Cleanup the fragment tracker before trying to find the next unbuffered fragment\n        const type =\n          this.audioOnly && !this.altAudio\n            ? ElementaryStreamTypes.AUDIO\n            : ElementaryStreamTypes.VIDEO;\n        const mediaBuffer =\n          (type === ElementaryStreamTypes.VIDEO\n            ? this.videoBuffer\n            : this.mediaBuffer) || this.media;\n        if (mediaBuffer) {\n          this.afterBufferFlushed(mediaBuffer, type, PlaylistLevelType.MAIN);\n        }\n      }\n      frag = this.getNextFragmentLoopLoading(\n        frag,\n        levelDetails,\n        bufferInfo,\n        PlaylistLevelType.MAIN,\n        maxBufLen,\n      );\n    }\n    if (!frag) {\n      return;\n    }\n    if (frag.initSegment && !frag.initSegment.data && !this.bitrateTest) {\n      frag = frag.initSegment;\n    }\n\n    this.loadFragment(frag, levelInfo, targetBufferTime);\n  }\n\n  protected loadFragment(\n    frag: Fragment,\n    level: Level,\n    targetBufferTime: number,\n  ) {\n    // Check if fragment is not loaded\n    const fragState = this.fragmentTracker.getState(frag);\n    this.fragCurrent = frag;\n    if (\n      fragState === FragmentState.NOT_LOADED ||\n      fragState === FragmentState.PARTIAL\n    ) {\n      if (frag.sn === 'initSegment') {\n        this._loadInitSegment(frag, level);\n      } else if (this.bitrateTest) {\n        this.log(\n          `Fragment ${frag.sn} of level ${frag.level} is being downloaded to test bitrate and will not be buffered`,\n        );\n        this._loadBitrateTestFrag(frag, level);\n      } else {\n        this.startFragRequested = true;\n        super.loadFragment(frag, level, targetBufferTime);\n      }\n    } else {\n      this.clearTrackerIfNeeded(frag);\n    }\n  }\n\n  private getBufferedFrag(position) {\n    return this.fragmentTracker.getBufferedFrag(\n      position,\n      PlaylistLevelType.MAIN,\n    );\n  }\n\n  private followingBufferedFrag(frag: Fragment | null) {\n    if (frag) {\n      // try to get range of next fragment (500ms after this range)\n      return this.getBufferedFrag(frag.end + 0.5);\n    }\n    return null;\n  }\n\n  /*\n    on immediate level switch :\n     - pause playback if playing\n     - cancel any pending load request\n     - and trigger a buffer flush\n  */\n  public immediateLevelSwitch() {\n    this.abortCurrentFrag();\n    this.flushMainBuffer(0, Number.POSITIVE_INFINITY);\n  }\n\n  /**\n   * try to switch ASAP without breaking video playback:\n   * in order to ensure smooth but quick level switching,\n   * we need to find the next flushable buffer range\n   * we should take into account new segment fetch time\n   */\n  public nextLevelSwitch() {\n    const { levels, media } = this;\n    // ensure that media is defined and that metadata are available (to retrieve currentTime)\n    if (media?.readyState) {\n      let fetchdelay;\n      const fragPlayingCurrent = this.getAppendedFrag(media.currentTime);\n      if (fragPlayingCurrent && fragPlayingCurrent.start > 1) {\n        // flush buffer preceding current fragment (flush until current fragment start offset)\n        // minus 1s to avoid video freezing, that could happen if we flush keyframe of current video ...\n        this.flushMainBuffer(0, fragPlayingCurrent.start - 1);\n      }\n      const levelDetails = this.getLevelDetails();\n      if (levelDetails?.live) {\n        const bufferInfo = this.getMainFwdBufferInfo();\n        // Do not flush in live stream with low buffer\n        if (!bufferInfo || bufferInfo.len < levelDetails.targetduration * 2) {\n          return;\n        }\n      }\n      if (!media.paused && levels) {\n        // add a safety delay of 1s\n        const nextLevelId = this.hls.nextLoadLevel;\n        const nextLevel = levels[nextLevelId];\n        const fragLastKbps = this.fragLastKbps;\n        if (fragLastKbps && this.fragCurrent) {\n          fetchdelay =\n            (this.fragCurrent.duration * nextLevel.maxBitrate) /\n              (1000 * fragLastKbps) +\n            1;\n        } else {\n          fetchdelay = 0;\n        }\n      } else {\n        fetchdelay = 0;\n      }\n      // this.log('fetchdelay:'+fetchdelay);\n      // find buffer range that will be reached once new fragment will be fetched\n      const bufferedFrag = this.getBufferedFrag(media.currentTime + fetchdelay);\n      if (bufferedFrag) {\n        // we can flush buffer range following this one without stalling playback\n        const nextBufferedFrag = this.followingBufferedFrag(bufferedFrag);\n        if (nextBufferedFrag) {\n          // if we are here, we can also cancel any loading/demuxing in progress, as they are useless\n          this.abortCurrentFrag();\n          // start flush position is in next buffered frag. Leave some padding for non-independent segments and smoother playback.\n          const maxStart = nextBufferedFrag.maxStartPTS\n            ? nextBufferedFrag.maxStartPTS\n            : nextBufferedFrag.start;\n          const fragDuration = nextBufferedFrag.duration;\n          const startPts = Math.max(\n            bufferedFrag.end,\n            maxStart +\n              Math.min(\n                Math.max(\n                  fragDuration - this.config.maxFragLookUpTolerance,\n                  fragDuration * (this.couldBacktrack ? 0.5 : 0.125),\n                ),\n                fragDuration * (this.couldBacktrack ? 0.75 : 0.25),\n              ),\n          );\n          this.flushMainBuffer(startPts, Number.POSITIVE_INFINITY);\n        }\n      }\n    }\n  }\n\n  private abortCurrentFrag() {\n    const fragCurrent = this.fragCurrent;\n    this.fragCurrent = null;\n    this.backtrackFragment = null;\n    if (fragCurrent) {\n      fragCurrent.abortRequests();\n      this.fragmentTracker.removeFragment(fragCurrent);\n    }\n    switch (this.state) {\n      case State.KEY_LOADING:\n      case State.FRAG_LOADING:\n      case State.FRAG_LOADING_WAITING_RETRY:\n      case State.PARSING:\n      case State.PARSED:\n        this.state = State.IDLE;\n        break;\n    }\n    this.nextLoadPosition = this.getLoadPosition();\n  }\n\n  protected flushMainBuffer(startOffset: number, endOffset: number) {\n    super.flushMainBuffer(\n      startOffset,\n      endOffset,\n      this.altAudio ? 'video' : null,\n    );\n  }\n\n  protected onMediaAttached(\n    event: Events.MEDIA_ATTACHED,\n    data: MediaAttachedData,\n  ) {\n    super.onMediaAttached(event, data);\n    const media = data.media;\n    this.onvplaying = this.onMediaPlaying.bind(this);\n    this.onvseeked = this.onMediaSeeked.bind(this);\n    media.addEventListener('playing', this.onvplaying as EventListener);\n    media.addEventListener('seeked', this.onvseeked as EventListener);\n    this.gapController = new GapController(\n      this.config,\n      media,\n      this.fragmentTracker,\n      this.hls,\n    );\n  }\n\n  protected onMediaDetaching() {\n    const { media } = this;\n    if (media && this.onvplaying && this.onvseeked) {\n      media.removeEventListener('playing', this.onvplaying);\n      media.removeEventListener('seeked', this.onvseeked);\n      this.onvplaying = this.onvseeked = null;\n      this.videoBuffer = null;\n    }\n    this.fragPlaying = null;\n    if (this.gapController) {\n      this.gapController.destroy();\n      this.gapController = null;\n    }\n    super.onMediaDetaching();\n  }\n\n  private onMediaPlaying() {\n    // tick to speed up FRAG_CHANGED triggering\n    this.tick();\n  }\n\n  private onMediaSeeked() {\n    const media = this.media;\n    const currentTime = media ? media.currentTime : null;\n    if (Number.isFinite(currentTime)) {\n      this.log(`Media seeked to ${(currentTime as number).toFixed(3)}`);\n    }\n\n    // If seeked was issued before buffer was appended do not tick immediately\n    const bufferInfo = this.getMainFwdBufferInfo();\n    if (bufferInfo === null || bufferInfo.len === 0) {\n      this.warn(\n        `Main forward buffer length on \"seeked\" event ${\n          bufferInfo ? bufferInfo.len : 'empty'\n        })`,\n      );\n      return;\n    }\n\n    // tick to speed up FRAG_CHANGED triggering\n    this.tick();\n  }\n\n  private onManifestLoading() {\n    // reset buffer on manifest loading\n    this.log('Trigger BUFFER_RESET');\n    this.hls.trigger(Events.BUFFER_RESET, undefined);\n    this.fragmentTracker.removeAllFragments();\n    this.couldBacktrack = false;\n    this.startPosition = this.lastCurrentTime = this.fragLastKbps = 0;\n    this.levels =\n      this.fragPlaying =\n      this.backtrackFragment =\n      this.levelLastLoaded =\n        null;\n    this.altAudio = this.audioOnly = this.startFragRequested = false;\n  }\n\n  private onManifestParsed(\n    event: Events.MANIFEST_PARSED,\n    data: ManifestParsedData,\n  ) {\n    // detect if we have different kind of audio codecs used amongst playlists\n    let aac = false;\n    let heaac = false;\n    data.levels.forEach((level) => {\n      const codec = level.audioCodec;\n      if (codec) {\n        aac = aac || codec.indexOf('mp4a.40.2') !== -1;\n        heaac = heaac || codec.indexOf('mp4a.40.5') !== -1;\n      }\n    });\n    this.audioCodecSwitch = aac && heaac && !changeTypeSupported();\n    if (this.audioCodecSwitch) {\n      this.log(\n        'Both AAC/HE-AAC audio found in levels; declaring level codec as HE-AAC',\n      );\n    }\n\n    this.levels = data.levels;\n    this.startFragRequested = false;\n  }\n\n  private onLevelLoading(event: Events.LEVEL_LOADING, data: LevelLoadingData) {\n    const { levels } = this;\n    if (!levels || this.state !== State.IDLE) {\n      return;\n    }\n    const level = levels[data.level];\n    if (\n      !level.details ||\n      (level.details.live && this.levelLastLoaded !== level) ||\n      this.waitForCdnTuneIn(level.details)\n    ) {\n      this.state = State.WAITING_LEVEL;\n    }\n  }\n\n  private onLevelLoaded(event: Events.LEVEL_LOADED, data: LevelLoadedData) {\n    const { levels } = this;\n    const newLevelId = data.level;\n    const newDetails = data.details;\n    const duration = newDetails.totalduration;\n\n    if (!levels) {\n      this.warn(`Levels were reset while loading level ${newLevelId}`);\n      return;\n    }\n    this.log(\n      `Level ${newLevelId} loaded [${newDetails.startSN},${newDetails.endSN}]${\n        newDetails.lastPartSn\n          ? `[part-${newDetails.lastPartSn}-${newDetails.lastPartIndex}]`\n          : ''\n      }, cc [${newDetails.startCC}, ${newDetails.endCC}] duration:${duration}`,\n    );\n\n    const curLevel = levels[newLevelId];\n    const fragCurrent = this.fragCurrent;\n    if (\n      fragCurrent &&\n      (this.state === State.FRAG_LOADING ||\n        this.state === State.FRAG_LOADING_WAITING_RETRY)\n    ) {\n      if (fragCurrent.level !== data.level && fragCurrent.loader) {\n        this.abortCurrentFrag();\n      }\n    }\n\n    let sliding = 0;\n    if (newDetails.live || curLevel.details?.live) {\n      this.checkLiveUpdate(newDetails);\n      if (newDetails.deltaUpdateFailed) {\n        return;\n      }\n      sliding = this.alignPlaylists(\n        newDetails,\n        curLevel.details,\n        this.levelLastLoaded?.details,\n      );\n    }\n    // override level info\n    curLevel.details = newDetails;\n    this.levelLastLoaded = curLevel;\n\n    this.hls.trigger(Events.LEVEL_UPDATED, {\n      details: newDetails,\n      level: newLevelId,\n    });\n\n    // only switch back to IDLE state if we were waiting for level to start downloading a new fragment\n    if (this.state === State.WAITING_LEVEL) {\n      if (this.waitForCdnTuneIn(newDetails)) {\n        // Wait for Low-Latency CDN Tune-in\n        return;\n      }\n      this.state = State.IDLE;\n    }\n\n    if (!this.startFragRequested) {\n      this.setStartPosition(newDetails, sliding);\n    } else if (newDetails.live) {\n      this.synchronizeToLiveEdge(newDetails);\n    }\n\n    // trigger handler right now\n    this.tick();\n  }\n\n  protected _handleFragmentLoadProgress(data: FragLoadedData) {\n    const { frag, part, payload } = data;\n    const { levels } = this;\n    if (!levels) {\n      this.warn(\n        `Levels were reset while fragment load was in progress. Fragment ${frag.sn} of level ${frag.level} will not be buffered`,\n      );\n      return;\n    }\n    const currentLevel = levels[frag.level];\n    const details = currentLevel.details as LevelDetails;\n    if (!details) {\n      this.warn(\n        `Dropping fragment ${frag.sn} of level ${frag.level} after level details were reset`,\n      );\n      this.fragmentTracker.removeFragment(frag);\n      return;\n    }\n    const videoCodec = currentLevel.videoCodec;\n\n    // time Offset is accurate if level PTS is known, or if playlist is not sliding (not live)\n    const accurateTimeOffset = details.PTSKnown || !details.live;\n    const initSegmentData = frag.initSegment?.data;\n    const audioCodec = this._getAudioCodec(currentLevel);\n\n    // transmux the MPEG-TS data to ISO-BMFF segments\n    // this.log(`Transmuxing ${frag.sn} of [${details.startSN} ,${details.endSN}],level ${frag.level}, cc ${frag.cc}`);\n    const transmuxer = (this.transmuxer =\n      this.transmuxer ||\n      new TransmuxerInterface(\n        this.hls,\n        PlaylistLevelType.MAIN,\n        this._handleTransmuxComplete.bind(this),\n        this._handleTransmuxerFlush.bind(this),\n      ));\n    const partIndex = part ? part.index : -1;\n    const partial = partIndex !== -1;\n    const chunkMeta = new ChunkMetadata(\n      frag.level,\n      frag.sn as number,\n      frag.stats.chunkCount,\n      payload.byteLength,\n      partIndex,\n      partial,\n    );\n    const initPTS = this.initPTS[frag.cc];\n\n    transmuxer.push(\n      payload,\n      initSegmentData,\n      audioCodec,\n      videoCodec,\n      frag,\n      part,\n      details.totalduration,\n      accurateTimeOffset,\n      chunkMeta,\n      initPTS,\n    );\n  }\n\n  private onAudioTrackSwitching(\n    event: Events.AUDIO_TRACK_SWITCHING,\n    data: AudioTrackSwitchingData,\n  ) {\n    // if any URL found on new audio track, it is an alternate audio track\n    const fromAltAudio = this.altAudio;\n    const altAudio = !!data.url;\n    // if we switch on main audio, ensure that main fragment scheduling is synced with media.buffered\n    // don't do anything if we switch to alt audio: audio stream controller is handling it.\n    // we will just have to change buffer scheduling on audioTrackSwitched\n    if (!altAudio) {\n      if (this.mediaBuffer !== this.media) {\n        this.log(\n          'Switching on main audio, use media.buffered to schedule main fragment loading',\n        );\n        this.mediaBuffer = this.media;\n        const fragCurrent = this.fragCurrent;\n        // we need to refill audio buffer from main: cancel any frag loading to speed up audio switch\n        if (fragCurrent) {\n          this.log('Switching to main audio track, cancel main fragment load');\n          fragCurrent.abortRequests();\n          this.fragmentTracker.removeFragment(fragCurrent);\n        }\n        // destroy transmuxer to force init segment generation (following audio switch)\n        this.resetTransmuxer();\n        // switch to IDLE state to load new fragment\n        this.resetLoadingState();\n      } else if (this.audioOnly) {\n        // Reset audio transmuxer so when switching back to main audio we're not still appending where we left off\n        this.resetTransmuxer();\n      }\n      const hls = this.hls;\n      // If switching from alt to main audio, flush all audio and trigger track switched\n      if (fromAltAudio) {\n        hls.trigger(Events.BUFFER_FLUSHING, {\n          startOffset: 0,\n          endOffset: Number.POSITIVE_INFINITY,\n          type: null,\n        });\n        this.fragmentTracker.removeAllFragments();\n      }\n      hls.trigger(Events.AUDIO_TRACK_SWITCHED, data);\n    }\n  }\n\n  private onAudioTrackSwitched(\n    event: Events.AUDIO_TRACK_SWITCHED,\n    data: AudioTrackSwitchedData,\n  ) {\n    const trackId = data.id;\n    const altAudio = !!this.hls.audioTracks[trackId].url;\n    if (altAudio) {\n      const videoBuffer = this.videoBuffer;\n      // if we switched on alternate audio, ensure that main fragment scheduling is synced with video sourcebuffer buffered\n      if (videoBuffer && this.mediaBuffer !== videoBuffer) {\n        this.log(\n          'Switching on alternate audio, use video.buffered to schedule main fragment loading',\n        );\n        this.mediaBuffer = videoBuffer;\n      }\n    }\n    this.altAudio = altAudio;\n    this.tick();\n  }\n\n  private onBufferCreated(\n    event: Events.BUFFER_CREATED,\n    data: BufferCreatedData,\n  ) {\n    const tracks = data.tracks;\n    let mediaTrack;\n    let name;\n    let alternate = false;\n    for (const type in tracks) {\n      const track = tracks[type];\n      if (track.id === 'main') {\n        name = type;\n        mediaTrack = track;\n        // keep video source buffer reference\n        if (type === 'video') {\n          const videoTrack = tracks[type];\n          if (videoTrack) {\n            this.videoBuffer = videoTrack.buffer;\n          }\n        }\n      } else {\n        alternate = true;\n      }\n    }\n    if (alternate && mediaTrack) {\n      this.log(\n        `Alternate track found, use ${name}.buffered to schedule main fragment loading`,\n      );\n      this.mediaBuffer = mediaTrack.buffer;\n    } else {\n      this.mediaBuffer = this.media;\n    }\n  }\n\n  private onFragBuffered(event: Events.FRAG_BUFFERED, data: FragBufferedData) {\n    const { frag, part } = data;\n    if (frag && frag.type !== PlaylistLevelType.MAIN) {\n      return;\n    }\n    if (this.fragContextChanged(frag)) {\n      // If a level switch was requested while a fragment was buffering, it will emit the FRAG_BUFFERED event upon completion\n      // Avoid setting state back to IDLE, since that will interfere with a level switch\n      this.warn(\n        `Fragment ${frag.sn}${part ? ' p: ' + part.index : ''} of level ${\n          frag.level\n        } finished buffering, but was aborted. state: ${this.state}`,\n      );\n      if (this.state === State.PARSED) {\n        this.state = State.IDLE;\n      }\n      return;\n    }\n    const stats = part ? part.stats : frag.stats;\n    this.fragLastKbps = Math.round(\n      (8 * stats.total) / (stats.buffering.end - stats.loading.first),\n    );\n    if (frag.sn !== 'initSegment') {\n      this.fragPrevious = frag;\n    }\n    this.fragBufferedComplete(frag, part);\n  }\n\n  private onError(event: Events.ERROR, data: ErrorData) {\n    if (data.fatal) {\n      this.state = State.ERROR;\n      return;\n    }\n    switch (data.details) {\n      case ErrorDetails.FRAG_GAP:\n      case ErrorDetails.FRAG_PARSING_ERROR:\n      case ErrorDetails.FRAG_DECRYPT_ERROR:\n      case ErrorDetails.FRAG_LOAD_ERROR:\n      case ErrorDetails.FRAG_LOAD_TIMEOUT:\n      case ErrorDetails.KEY_LOAD_ERROR:\n      case ErrorDetails.KEY_LOAD_TIMEOUT:\n        this.onFragmentOrKeyLoadError(PlaylistLevelType.MAIN, data);\n        break;\n      case ErrorDetails.LEVEL_LOAD_ERROR:\n      case ErrorDetails.LEVEL_LOAD_TIMEOUT:\n      case ErrorDetails.LEVEL_PARSING_ERROR:\n        // in case of non fatal error while loading level, if level controller is not retrying to load level, switch back to IDLE\n        if (\n          !data.levelRetry &&\n          this.state === State.WAITING_LEVEL &&\n          data.context?.type === PlaylistContextType.LEVEL\n        ) {\n          this.state = State.IDLE;\n        }\n        break;\n      case ErrorDetails.BUFFER_APPEND_ERROR:\n      case ErrorDetails.BUFFER_FULL_ERROR:\n        if (!data.parent || data.parent !== 'main') {\n          return;\n        }\n        if (data.details === ErrorDetails.BUFFER_APPEND_ERROR) {\n          this.resetLoadingState();\n          return;\n        }\n        if (this.reduceLengthAndFlushBuffer(data)) {\n          this.flushMainBuffer(0, Number.POSITIVE_INFINITY);\n        }\n        break;\n      case ErrorDetails.INTERNAL_EXCEPTION:\n        this.recoverWorkerError(data);\n        break;\n      default:\n        break;\n    }\n  }\n\n  // Checks the health of the buffer and attempts to resolve playback stalls.\n  private checkBuffer() {\n    const { media, gapController } = this;\n    if (!media || !gapController || !media.readyState) {\n      // Exit early if we don't have media or if the media hasn't buffered anything yet (readyState 0)\n      return;\n    }\n\n    if (this.loadedmetadata || !BufferHelper.getBuffered(media).length) {\n      // Resolve gaps using the main buffer, whose ranges are the intersections of the A/V sourcebuffers\n      const activeFrag = this.state !== State.IDLE ? this.fragCurrent : null;\n      gapController.poll(this.lastCurrentTime, activeFrag);\n    }\n\n    this.lastCurrentTime = media.currentTime;\n  }\n\n  private onFragLoadEmergencyAborted() {\n    this.state = State.IDLE;\n    // if loadedmetadata is not set, it means that we are emergency switch down on first frag\n    // in that case, reset startFragRequested flag\n    if (!this.loadedmetadata) {\n      this.startFragRequested = false;\n      this.nextLoadPosition = this.startPosition;\n    }\n    this.tickImmediate();\n  }\n\n  private onBufferFlushed(\n    event: Events.BUFFER_FLUSHED,\n    { type }: BufferFlushedData,\n  ) {\n    if (\n      type !== ElementaryStreamTypes.AUDIO ||\n      (this.audioOnly && !this.altAudio)\n    ) {\n      const mediaBuffer =\n        (type === ElementaryStreamTypes.VIDEO\n          ? this.videoBuffer\n          : this.mediaBuffer) || this.media;\n      this.afterBufferFlushed(mediaBuffer, type, PlaylistLevelType.MAIN);\n      this.tick();\n    }\n  }\n\n  private onLevelsUpdated(\n    event: Events.LEVELS_UPDATED,\n    data: LevelsUpdatedData,\n  ) {\n    if (this.level > -1 && this.fragCurrent) {\n      this.level = this.fragCurrent.level;\n    }\n    this.levels = data.levels;\n  }\n\n  public swapAudioCodec() {\n    this.audioCodecSwap = !this.audioCodecSwap;\n  }\n\n  /**\n   * Seeks to the set startPosition if not equal to the mediaElement's current time.\n   */\n  protected seekToStartPos() {\n    const { media } = this;\n    if (!media) {\n      return;\n    }\n    const currentTime = media.currentTime;\n    let startPosition = this.startPosition;\n    // only adjust currentTime if different from startPosition or if startPosition not buffered\n    // at that stage, there should be only one buffered range, as we reach that code after first fragment has been buffered\n    if (startPosition >= 0 && currentTime < startPosition) {\n      if (media.seeking) {\n        this.log(\n          `could not seek to ${startPosition}, already seeking at ${currentTime}`,\n        );\n        return;\n      }\n      const buffered = BufferHelper.getBuffered(media);\n      const bufferStart = buffered.length ? buffered.start(0) : 0;\n      const delta = bufferStart - startPosition;\n      if (\n        delta > 0 &&\n        (delta < this.config.maxBufferHole ||\n          delta < this.config.maxFragLookUpTolerance)\n      ) {\n        this.log(`adjusting start position by ${delta} to match buffer start`);\n        startPosition += delta;\n        this.startPosition = startPosition;\n      }\n      this.log(\n        `seek to target start position ${startPosition} from current time ${currentTime}`,\n      );\n      media.currentTime = startPosition;\n    }\n  }\n\n  private _getAudioCodec(currentLevel) {\n    let audioCodec = this.config.defaultAudioCodec || currentLevel.audioCodec;\n    if (this.audioCodecSwap && audioCodec) {\n      this.log('Swapping audio codec');\n      if (audioCodec.indexOf('mp4a.40.5') !== -1) {\n        audioCodec = 'mp4a.40.2';\n      } else {\n        audioCodec = 'mp4a.40.5';\n      }\n    }\n\n    return audioCodec;\n  }\n\n  private _loadBitrateTestFrag(frag: Fragment, level: Level) {\n    frag.bitrateTest = true;\n    this._doFragLoad(frag, level).then((data) => {\n      const { hls } = this;\n      if (!data || this.fragContextChanged(frag)) {\n        return;\n      }\n      level.fragmentError = 0;\n      this.state = State.IDLE;\n      this.startFragRequested = false;\n      this.bitrateTest = false;\n      const stats = frag.stats;\n      // Bitrate tests fragments are neither parsed nor buffered\n      stats.parsing.start =\n        stats.parsing.end =\n        stats.buffering.start =\n        stats.buffering.end =\n          self.performance.now();\n      hls.trigger(Events.FRAG_LOADED, data as FragLoadedData);\n      frag.bitrateTest = false;\n    });\n  }\n\n  private _handleTransmuxComplete(transmuxResult: TransmuxerResult) {\n    const id = 'main';\n    const { hls } = this;\n    const { remuxResult, chunkMeta } = transmuxResult;\n\n    const context = this.getCurrentContext(chunkMeta);\n    if (!context) {\n      this.resetWhenMissingContext(chunkMeta);\n      return;\n    }\n    const { frag, part, level } = context;\n    const { video, text, id3, initSegment } = remuxResult;\n    const { details } = level;\n    // The audio-stream-controller handles audio buffering if Hls.js is playing an alternate audio track\n    const audio = this.altAudio ? undefined : remuxResult.audio;\n\n    // Check if the current fragment has been aborted. We check this by first seeing if we're still playing the current level.\n    // If we are, subsequently check if the currently loading fragment (fragCurrent) has changed.\n    if (this.fragContextChanged(frag)) {\n      this.fragmentTracker.removeFragment(frag);\n      return;\n    }\n\n    this.state = State.PARSING;\n\n    if (initSegment) {\n      if (initSegment?.tracks) {\n        const mapFragment = frag.initSegment || frag;\n        this._bufferInitSegment(\n          level,\n          initSegment.tracks,\n          mapFragment,\n          chunkMeta,\n        );\n        hls.trigger(Events.FRAG_PARSING_INIT_SEGMENT, {\n          frag: mapFragment,\n          id,\n          tracks: initSegment.tracks,\n        });\n      }\n\n      // This would be nice if Number.isFinite acted as a typeguard, but it doesn't. See: https://github.com/Microsoft/TypeScript/issues/10038\n      const initPTS = initSegment.initPTS as number;\n      const timescale = initSegment.timescale as number;\n      if (Number.isFinite(initPTS)) {\n        this.initPTS[frag.cc] = { baseTime: initPTS, timescale };\n        hls.trigger(Events.INIT_PTS_FOUND, { frag, id, initPTS, timescale });\n      }\n    }\n\n    // Avoid buffering if backtracking this fragment\n    if (video && details && frag.sn !== 'initSegment') {\n      const prevFrag = details.fragments[frag.sn - 1 - details.startSN];\n      const isFirstFragment = frag.sn === details.startSN;\n      const isFirstInDiscontinuity = !prevFrag || frag.cc > prevFrag.cc;\n      if (remuxResult.independent !== false) {\n        const { startPTS, endPTS, startDTS, endDTS } = video;\n        if (part) {\n          part.elementaryStreams[video.type] = {\n            startPTS,\n            endPTS,\n            startDTS,\n            endDTS,\n          };\n        } else {\n          if (\n            video.firstKeyFrame &&\n            video.independent &&\n            chunkMeta.id === 1 &&\n            !isFirstInDiscontinuity\n          ) {\n            this.couldBacktrack = true;\n          }\n          if (video.dropped && video.independent) {\n            // Backtrack if dropped frames create a gap after currentTime\n\n            const bufferInfo = this.getMainFwdBufferInfo();\n            const targetBufferTime =\n              (bufferInfo ? bufferInfo.end : this.getLoadPosition()) +\n              this.config.maxBufferHole;\n            const startTime = video.firstKeyFramePTS\n              ? video.firstKeyFramePTS\n              : startPTS;\n            if (\n              !isFirstFragment &&\n              targetBufferTime < startTime - this.config.maxBufferHole &&\n              !isFirstInDiscontinuity\n            ) {\n              this.backtrack(frag);\n              return;\n            } else if (isFirstInDiscontinuity) {\n              // Mark segment with a gap to avoid loop loading\n              frag.gap = true;\n            }\n            // Set video stream start to fragment start so that truncated samples do not distort the timeline, and mark it partial\n            frag.setElementaryStreamInfo(\n              video.type as ElementaryStreamTypes,\n              frag.start,\n              endPTS,\n              frag.start,\n              endDTS,\n              true,\n            );\n          } else if (isFirstFragment && startPTS > MAX_START_GAP_JUMP) {\n            // Mark segment with a gap to skip large start gap\n            frag.gap = true;\n          }\n        }\n        frag.setElementaryStreamInfo(\n          video.type as ElementaryStreamTypes,\n          startPTS,\n          endPTS,\n          startDTS,\n          endDTS,\n        );\n        if (this.backtrackFragment) {\n          this.backtrackFragment = frag;\n        }\n        this.bufferFragmentData(\n          video,\n          frag,\n          part,\n          chunkMeta,\n          isFirstFragment || isFirstInDiscontinuity,\n        );\n      } else if (isFirstFragment || isFirstInDiscontinuity) {\n        // Mark segment with a gap to avoid loop loading\n        frag.gap = true;\n      } else {\n        this.backtrack(frag);\n        return;\n      }\n    }\n\n    if (audio) {\n      const { startPTS, endPTS, startDTS, endDTS } = audio;\n      if (part) {\n        part.elementaryStreams[ElementaryStreamTypes.AUDIO] = {\n          startPTS,\n          endPTS,\n          startDTS,\n          endDTS,\n        };\n      }\n      frag.setElementaryStreamInfo(\n        ElementaryStreamTypes.AUDIO,\n        startPTS,\n        endPTS,\n        startDTS,\n        endDTS,\n      );\n      this.bufferFragmentData(audio, frag, part, chunkMeta);\n    }\n\n    if (details && id3?.samples?.length) {\n      const emittedID3: FragParsingMetadataData = {\n        id,\n        frag,\n        details,\n        samples: id3.samples,\n      };\n      hls.trigger(Events.FRAG_PARSING_METADATA, emittedID3);\n    }\n    if (details && text) {\n      const emittedText: FragParsingUserdataData = {\n        id,\n        frag,\n        details,\n        samples: text.samples,\n      };\n      hls.trigger(Events.FRAG_PARSING_USERDATA, emittedText);\n    }\n  }\n\n  private _bufferInitSegment(\n    currentLevel: Level,\n    tracks: TrackSet,\n    frag: Fragment,\n    chunkMeta: ChunkMetadata,\n  ) {\n    if (this.state !== State.PARSING) {\n      return;\n    }\n\n    this.audioOnly = !!tracks.audio && !tracks.video;\n\n    // if audio track is expected to come from audio stream controller, discard any coming from main\n    if (this.altAudio && !this.audioOnly) {\n      delete tracks.audio;\n    }\n    // include levelCodec in audio and video tracks\n    const { audio, video, audiovideo } = tracks;\n    if (audio) {\n      let audioCodec = currentLevel.audioCodec;\n      const ua = navigator.userAgent.toLowerCase();\n      if (this.audioCodecSwitch) {\n        if (audioCodec) {\n          if (audioCodec.indexOf('mp4a.40.5') !== -1) {\n            audioCodec = 'mp4a.40.2';\n          } else {\n            audioCodec = 'mp4a.40.5';\n          }\n        }\n        // In the case that AAC and HE-AAC audio codecs are signalled in manifest,\n        // force HE-AAC, as it seems that most browsers prefers it.\n        // don't force HE-AAC if mono stream, or in Firefox\n        const audioMetadata = audio.metadata;\n        if (\n          audioMetadata &&\n          'channelCount' in audioMetadata &&\n          (audioMetadata.channelCount || 1) !== 1 &&\n          ua.indexOf('firefox') === -1\n        ) {\n          audioCodec = 'mp4a.40.5';\n        }\n      }\n      // HE-AAC is broken on Android, always signal audio codec as AAC even if variant manifest states otherwise\n      if (\n        audioCodec &&\n        audioCodec.indexOf('mp4a.40.5') !== -1 &&\n        ua.indexOf('android') !== -1 &&\n        audio.container !== 'audio/mpeg'\n      ) {\n        // Exclude mpeg audio\n        audioCodec = 'mp4a.40.2';\n        this.log(`Android: force audio codec to ${audioCodec}`);\n      }\n      if (currentLevel.audioCodec && currentLevel.audioCodec !== audioCodec) {\n        this.log(\n          `Swapping manifest audio codec \"${currentLevel.audioCodec}\" for \"${audioCodec}\"`,\n        );\n      }\n      audio.levelCodec = audioCodec;\n      audio.id = 'main';\n      this.log(\n        `Init audio buffer, container:${\n          audio.container\n        }, codecs[selected/level/parsed]=[${audioCodec || ''}/${\n          currentLevel.audioCodec || ''\n        }/${audio.codec}]`,\n      );\n    }\n    if (video) {\n      video.levelCodec = currentLevel.videoCodec;\n      video.id = 'main';\n      this.log(\n        `Init video buffer, container:${\n          video.container\n        }, codecs[level/parsed]=[${currentLevel.videoCodec || ''}/${\n          video.codec\n        }]`,\n      );\n    }\n    if (audiovideo) {\n      this.log(\n        `Init audiovideo buffer, container:${audiovideo.container}, codecs[level/parsed]=[${currentLevel.codecs}/${audiovideo.codec}]`,\n      );\n    }\n    this.hls.trigger(Events.BUFFER_CODECS, tracks);\n    // loop through tracks that are going to be provided to bufferController\n    Object.keys(tracks).forEach((trackName) => {\n      const track = tracks[trackName];\n      const initSegment = track.initSegment;\n      if (initSegment?.byteLength) {\n        this.hls.trigger(Events.BUFFER_APPENDING, {\n          type: trackName as SourceBufferName,\n          data: initSegment,\n          frag,\n          part: null,\n          chunkMeta,\n          parent: frag.type,\n        });\n      }\n    });\n    // trigger handler right now\n    this.tickImmediate();\n  }\n\n  public getMainFwdBufferInfo(): BufferInfo | null {\n    return this.getFwdBufferInfo(\n      this.mediaBuffer ? this.mediaBuffer : this.media,\n      PlaylistLevelType.MAIN,\n    );\n  }\n\n  private backtrack(frag: Fragment) {\n    this.couldBacktrack = true;\n    // Causes findFragments to backtrack through fragments to find the keyframe\n    this.backtrackFragment = frag;\n    this.resetTransmuxer();\n    this.flushBufferGap(frag);\n    this.fragmentTracker.removeFragment(frag);\n    this.fragPrevious = null;\n    this.nextLoadPosition = frag.start;\n    this.state = State.IDLE;\n  }\n\n  private checkFragmentChanged() {\n    const video = this.media;\n    let fragPlayingCurrent: Fragment | null = null;\n    if (video && video.readyState > 1 && video.seeking === false) {\n      const currentTime = video.currentTime;\n      /* if video element is in seeked state, currentTime can only increase.\n        (assuming that playback rate is positive ...)\n        As sometimes currentTime jumps back to zero after a\n        media decode error, check this, to avoid seeking back to\n        wrong position after a media decode error\n      */\n\n      if (BufferHelper.isBuffered(video, currentTime)) {\n        fragPlayingCurrent = this.getAppendedFrag(currentTime);\n      } else if (BufferHelper.isBuffered(video, currentTime + 0.1)) {\n        /* ensure that FRAG_CHANGED event is triggered at startup,\n          when first video frame is displayed and playback is paused.\n          add a tolerance of 100ms, in case current position is not buffered,\n          check if current pos+100ms is buffered and use that buffer range\n          for FRAG_CHANGED event reporting */\n        fragPlayingCurrent = this.getAppendedFrag(currentTime + 0.1);\n      }\n      if (fragPlayingCurrent) {\n        this.backtrackFragment = null;\n        const fragPlaying = this.fragPlaying;\n        const fragCurrentLevel = fragPlayingCurrent.level;\n        if (\n          !fragPlaying ||\n          fragPlayingCurrent.sn !== fragPlaying.sn ||\n          fragPlaying.level !== fragCurrentLevel\n        ) {\n          this.fragPlaying = fragPlayingCurrent;\n          this.hls.trigger(Events.FRAG_CHANGED, { frag: fragPlayingCurrent });\n          if (!fragPlaying || fragPlaying.level !== fragCurrentLevel) {\n            this.hls.trigger(Events.LEVEL_SWITCHED, {\n              level: fragCurrentLevel,\n            });\n          }\n        }\n      }\n    }\n  }\n\n  get nextLevel(): number {\n    const frag = this.nextBufferedFrag;\n    if (frag) {\n      return frag.level;\n    }\n    return -1;\n  }\n\n  get currentFrag(): Fragment | null {\n    const media = this.media;\n    if (media) {\n      return this.fragPlaying || this.getAppendedFrag(media.currentTime);\n    }\n    return null;\n  }\n\n  get currentProgramDateTime(): Date | null {\n    const media = this.media;\n    if (media) {\n      const currentTime = media.currentTime;\n      const frag = this.currentFrag;\n      if (\n        frag &&\n        Number.isFinite(currentTime) &&\n        Number.isFinite(frag.programDateTime)\n      ) {\n        const epocMs =\n          (frag.programDateTime as number) + (currentTime - frag.start) * 1000;\n        return new Date(epocMs);\n      }\n    }\n    return null;\n  }\n\n  get currentLevel(): number {\n    const frag = this.currentFrag;\n    if (frag) {\n      return frag.level;\n    }\n    return -1;\n  }\n\n  get nextBufferedFrag() {\n    const frag = this.currentFrag;\n    if (frag) {\n      return this.followingBufferedFrag(frag);\n    }\n    return null;\n  }\n\n  get forceStartLoad() {\n    return this._forceStartLoad;\n  }\n}\n", "import { buildAbsoluteURL } from 'url-toolkit';\nimport PlaylistLoader from './loader/playlist-loader';\nimport ID3TrackController from './controller/id3-track-controller';\nimport LatencyController from './controller/latency-controller';\nimport LevelController from './controller/level-controller';\nimport { FragmentTracker } from './controller/fragment-tracker';\nimport KeyLoader from './loader/key-loader';\nimport StreamController from './controller/stream-controller';\nimport { isMSESupported, isSupported } from './is-supported';\nimport { getMediaSource } from './utils/mediasource-helper';\nimport { logger, enableLogs } from './utils/logger';\nimport { enableStreamingMode, hlsDefaultConfig, mergeConfig } from './config';\nimport { EventEmitter } from 'eventemitter3';\nimport { Events } from './events';\nimport { ErrorTypes, ErrorDetails } from './errors';\nimport { isHdcpLevel, type HdcpLevel, type Level } from './types/level';\nimport type { HlsEventEmitter, HlsListeners } from './events';\nimport type AudioTrackController from './controller/audio-track-controller';\nimport type AbrController from './controller/abr-controller';\nimport type BufferController from './controller/buffer-controller';\nimport type CapLevelController from './controller/cap-level-controller';\nimport type CMCDController from './controller/cmcd-controller';\nimport type EMEController from './controller/eme-controller';\nimport type SubtitleTrackController from './controller/subtitle-track-controller';\nimport type {\n  AbrComponentAPI,\n  ComponentAPI,\n  NetworkComponentAPI,\n} from './types/component-api';\nimport type {\n  AudioSelectionOption,\n  MediaPlaylist,\n  SubtitleSelectionOption,\n  VideoSelectionOption,\n} from './types/media-playlist';\nimport type { HlsConfig } from './config';\nimport type { BufferInfo } from './utils/buffer-helper';\nimport type AudioStreamController from './controller/audio-stream-controller';\nimport type BasePlaylistController from './controller/base-playlist-controller';\nimport type BaseStreamController from './controller/base-stream-controller';\nimport type ContentSteeringController from './controller/content-steering-controller';\nimport type ErrorController from './controller/error-controller';\nimport type FPSController from './controller/fps-controller';\n\n/**\n * The `Hls` class is the core of the HLS.js library used to instantiate player instances.\n * @public\n */\nexport default class Hls implements HlsEventEmitter {\n  private static defaultConfig: HlsConfig | undefined;\n\n  /**\n   * The runtime configuration used by the player. At instantiation this is combination of `hls.userConfig` merged over `Hls.DefaultConfig`.\n   */\n  public readonly config: HlsConfig;\n\n  /**\n   * The configuration object provided on player instantiation.\n   */\n  public readonly userConfig: Partial<HlsConfig>;\n\n  private coreComponents: ComponentAPI[];\n  private networkControllers: NetworkComponentAPI[];\n  private started: boolean = false;\n  private _emitter: HlsEventEmitter = new EventEmitter();\n  private _autoLevelCapping: number = -1;\n  private _maxHdcpLevel: HdcpLevel = null;\n  private abrController: AbrComponentAPI;\n  private bufferController: BufferController;\n  private capLevelController: CapLevelController;\n  private latencyController: LatencyController;\n  private levelController: LevelController;\n  private streamController: StreamController;\n  private audioTrackController: AudioTrackController;\n  private subtitleTrackController: SubtitleTrackController;\n  private emeController: EMEController;\n  private cmcdController: CMCDController;\n  private _media: HTMLMediaElement | null = null;\n  private url: string | null = null;\n  private triggeringException?: boolean;\n\n  /**\n   * Get the video-dev/hls.js package version.\n   */\n  static get version(): string {\n    return __VERSION__;\n  }\n\n  /**\n   * Check if the required MediaSource Extensions are available.\n   */\n  static isMSESupported(): boolean {\n    return isMSESupported();\n  }\n\n  /**\n   * Check if MediaSource Extensions are available and isTypeSupported checks pass for any baseline codecs.\n   */\n  static isSupported(): boolean {\n    return isSupported();\n  }\n\n  /**\n   * Get the MediaSource global used for MSE playback (ManagedMediaSource, MediaSource, or WebKitMediaSource).\n   */\n  static getMediaSource(): typeof MediaSource | undefined {\n    return getMediaSource();\n  }\n\n  static get Events(): typeof Events {\n    return Events;\n  }\n\n  static get ErrorTypes(): typeof ErrorTypes {\n    return ErrorTypes;\n  }\n\n  static get ErrorDetails(): typeof ErrorDetails {\n    return ErrorDetails;\n  }\n\n  /**\n   * Get the default configuration applied to new instances.\n   */\n  static get DefaultConfig(): HlsConfig {\n    if (!Hls.defaultConfig) {\n      return hlsDefaultConfig;\n    }\n\n    return Hls.defaultConfig;\n  }\n\n  /**\n   * Replace the default configuration applied to new instances.\n   */\n  static set DefaultConfig(defaultConfig: HlsConfig) {\n    Hls.defaultConfig = defaultConfig;\n  }\n\n  /**\n   * Creates an instance of an HLS client that can attach to exactly one `HTMLMediaElement`.\n   * @param userConfig - Configuration options applied over `Hls.DefaultConfig`\n   */\n  constructor(userConfig: Partial<HlsConfig> = {}) {\n    enableLogs(userConfig.debug || false, 'Hls instance');\n    const config = (this.config = mergeConfig(Hls.DefaultConfig, userConfig));\n    this.userConfig = userConfig;\n\n    if (config.progressive) {\n      enableStreamingMode(config);\n    }\n\n    // core controllers and network loaders\n    const {\n      abrController: ConfigAbrController,\n      bufferController: ConfigBufferController,\n      capLevelController: ConfigCapLevelController,\n      errorController: ConfigErrorController,\n      fpsController: ConfigFpsController,\n    } = config;\n    const errorController = new ConfigErrorController(this);\n    const abrController = (this.abrController = new ConfigAbrController(this));\n    const bufferController = (this.bufferController =\n      new ConfigBufferController(this));\n    const capLevelController = (this.capLevelController =\n      new ConfigCapLevelController(this));\n\n    const fpsController = new ConfigFpsController(this);\n    const playListLoader = new PlaylistLoader(this);\n    const id3TrackController = new ID3TrackController(this);\n\n    const ConfigContentSteeringController = config.contentSteeringController;\n    // ConentSteeringController is defined before LevelController to receive Multivariant Playlist events first\n    const contentSteering = ConfigContentSteeringController\n      ? new ConfigContentSteeringController(this)\n      : null;\n    const levelController = (this.levelController = new LevelController(\n      this,\n      contentSteering,\n    ));\n    // FragmentTracker must be defined before StreamController because the order of event handling is important\n    const fragmentTracker = new FragmentTracker(this);\n    const keyLoader = new KeyLoader(this.config);\n    const streamController = (this.streamController = new StreamController(\n      this,\n      fragmentTracker,\n      keyLoader,\n    ));\n\n    // Cap level controller uses streamController to flush the buffer\n    capLevelController.setStreamController(streamController);\n    // fpsController uses streamController to switch when frames are being dropped\n    fpsController.setStreamController(streamController);\n\n    const networkControllers: NetworkComponentAPI[] = [\n      playListLoader,\n      levelController,\n      streamController,\n    ];\n    if (contentSteering) {\n      networkControllers.splice(1, 0, contentSteering);\n    }\n\n    this.networkControllers = networkControllers;\n    const coreComponents: ComponentAPI[] = [\n      abrController,\n      bufferController,\n      capLevelController,\n      fpsController,\n      id3TrackController,\n      fragmentTracker,\n    ];\n\n    this.audioTrackController = this.createController(\n      config.audioTrackController,\n      networkControllers,\n    );\n    const AudioStreamControllerClass = config.audioStreamController;\n    if (AudioStreamControllerClass) {\n      networkControllers.push(\n        new AudioStreamControllerClass(this, fragmentTracker, keyLoader),\n      );\n    }\n    // subtitleTrackController must be defined before subtitleStreamController because the order of event handling is important\n    this.subtitleTrackController = this.createController(\n      config.subtitleTrackController,\n      networkControllers,\n    );\n    const SubtitleStreamControllerClass = config.subtitleStreamController;\n    if (SubtitleStreamControllerClass) {\n      networkControllers.push(\n        new SubtitleStreamControllerClass(this, fragmentTracker, keyLoader),\n      );\n    }\n    this.createController(config.timelineController, coreComponents);\n    keyLoader.emeController = this.emeController = this.createController(\n      config.emeController,\n      coreComponents,\n    );\n    this.cmcdController = this.createController(\n      config.cmcdController,\n      coreComponents,\n    );\n    this.latencyController = this.createController(\n      LatencyController,\n      coreComponents,\n    );\n\n    this.coreComponents = coreComponents;\n\n    // Error controller handles errors before and after all other controllers\n    // This listener will be invoked after all other controllers error listeners\n    networkControllers.push(errorController);\n    const onErrorOut = errorController.onErrorOut;\n    if (typeof onErrorOut === 'function') {\n      this.on(Events.ERROR, onErrorOut, errorController);\n    }\n  }\n\n  createController(ControllerClass, components) {\n    if (ControllerClass) {\n      const controllerInstance = new ControllerClass(this);\n      if (components) {\n        components.push(controllerInstance);\n      }\n      return controllerInstance;\n    }\n    return null;\n  }\n\n  // Delegate the EventEmitter through the public API of Hls.js\n  on<E extends keyof HlsListeners, Context = undefined>(\n    event: E,\n    listener: HlsListeners[E],\n    context: Context = this as any,\n  ) {\n    this._emitter.on(event, listener, context);\n  }\n\n  once<E extends keyof HlsListeners, Context = undefined>(\n    event: E,\n    listener: HlsListeners[E],\n    context: Context = this as any,\n  ) {\n    this._emitter.once(event, listener, context);\n  }\n\n  removeAllListeners<E extends keyof HlsListeners>(event?: E | undefined) {\n    this._emitter.removeAllListeners(event);\n  }\n\n  off<E extends keyof HlsListeners, Context = undefined>(\n    event: E,\n    listener?: HlsListeners[E] | undefined,\n    context: Context = this as any,\n    once?: boolean | undefined,\n  ) {\n    this._emitter.off(event, listener, context, once);\n  }\n\n  listeners<E extends keyof HlsListeners>(event: E): HlsListeners[E][] {\n    return this._emitter.listeners(event);\n  }\n\n  emit<E extends keyof HlsListeners>(\n    event: E,\n    name: E,\n    eventObject: Parameters<HlsListeners[E]>[1],\n  ): boolean {\n    return this._emitter.emit(event, name, eventObject);\n  }\n\n  trigger<E extends keyof HlsListeners>(\n    event: E,\n    eventObject: Parameters<HlsListeners[E]>[1],\n  ): boolean {\n    if (this.config.debug) {\n      return this.emit(event, event, eventObject);\n    } else {\n      try {\n        return this.emit(event, event, eventObject);\n      } catch (error) {\n        logger.error(\n          'An internal error happened while handling event ' +\n            event +\n            '. Error message: \"' +\n            error.message +\n            '\". Here is a stacktrace:',\n          error,\n        );\n        // Prevent recursion in error event handlers that throw #5497\n        if (!this.triggeringException) {\n          this.triggeringException = true;\n          const fatal = event === Events.ERROR;\n          this.trigger(Events.ERROR, {\n            type: ErrorTypes.OTHER_ERROR,\n            details: ErrorDetails.INTERNAL_EXCEPTION,\n            fatal,\n            event,\n            error,\n          });\n          this.triggeringException = false;\n        }\n      }\n    }\n    return false;\n  }\n\n  listenerCount<E extends keyof HlsListeners>(event: E): number {\n    return this._emitter.listenerCount(event);\n  }\n\n  /**\n   * Dispose of the instance\n   */\n  destroy() {\n    logger.log('destroy');\n    this.trigger(Events.DESTROYING, undefined);\n    this.detachMedia();\n    this.removeAllListeners();\n    this._autoLevelCapping = -1;\n    this.url = null;\n\n    this.networkControllers.forEach((component) => component.destroy());\n    this.networkControllers.length = 0;\n\n    this.coreComponents.forEach((component) => component.destroy());\n    this.coreComponents.length = 0;\n    // Remove any references that could be held in config options or callbacks\n    const config = this.config;\n    config.xhrSetup = config.fetchSetup = undefined;\n    // @ts-ignore\n    this.userConfig = null;\n  }\n\n  /**\n   * Attaches Hls.js to a media element\n   */\n  attachMedia(media: HTMLMediaElement) {\n    logger.log('attachMedia');\n    this._media = media;\n    this.trigger(Events.MEDIA_ATTACHING, { media: media });\n  }\n\n  /**\n   * Detach Hls.js from the media\n   */\n  detachMedia() {\n    logger.log('detachMedia');\n    this.trigger(Events.MEDIA_DETACHING, undefined);\n    this._media = null;\n  }\n\n  /**\n   * Set the source URL. Can be relative or absolute.\n   */\n  loadSource(url: string) {\n    this.stopLoad();\n    const media = this.media;\n    const loadedSource = this.url;\n    const loadingSource = (this.url = buildAbsoluteURL(\n      self.location.href,\n      url,\n      {\n        alwaysNormalize: true,\n      },\n    ));\n    this._autoLevelCapping = -1;\n    this._maxHdcpLevel = null;\n    logger.log(`loadSource:${loadingSource}`);\n    if (\n      media &&\n      loadedSource &&\n      (loadedSource !== loadingSource || this.bufferController.hasSourceTypes())\n    ) {\n      this.detachMedia();\n      this.attachMedia(media);\n    }\n    // when attaching to a source URL, trigger a playlist load\n    this.trigger(Events.MANIFEST_LOADING, { url: url });\n  }\n\n  /**\n   * Start loading data from the stream source.\n   * Depending on default config, client starts loading automatically when a source is set.\n   *\n   * @param startPosition - Set the start position to stream from.\n   * Defaults to -1 (None: starts from earliest point)\n   */\n  startLoad(startPosition: number = -1) {\n    logger.log(`startLoad(${startPosition})`);\n    this.started = true;\n    this.networkControllers.forEach((controller) => {\n      controller.startLoad(startPosition);\n    });\n  }\n\n  /**\n   * Stop loading of any stream data.\n   */\n  stopLoad() {\n    logger.log('stopLoad');\n    this.started = false;\n    this.networkControllers.forEach((controller) => {\n      controller.stopLoad();\n    });\n  }\n\n  /**\n   * Resumes stream controller segment loading if previously started.\n   */\n  resumeBuffering() {\n    if (this.started) {\n      this.networkControllers.forEach((controller) => {\n        if ('fragmentLoader' in controller) {\n          controller.startLoad(-1);\n        }\n      });\n    }\n  }\n\n  /**\n   * Stops stream controller segment loading without changing 'started' state like stopLoad().\n   * This allows for media buffering to be paused without interupting playlist loading.\n   */\n  pauseBuffering() {\n    this.networkControllers.forEach((controller) => {\n      if ('fragmentLoader' in controller) {\n        controller.stopLoad();\n      }\n    });\n  }\n\n  /**\n   * Swap through possible audio codecs in the stream (for example to switch from stereo to 5.1)\n   */\n  swapAudioCodec() {\n    logger.log('swapAudioCodec');\n    this.streamController.swapAudioCodec();\n  }\n\n  /**\n   * When the media-element fails, this allows to detach and then re-attach it\n   * as one call (convenience method).\n   *\n   * Automatic recovery of media-errors by this process is configurable.\n   */\n  recoverMediaError() {\n    logger.log('recoverMediaError');\n    const media = this._media;\n    this.detachMedia();\n    if (media) {\n      this.attachMedia(media);\n    }\n  }\n\n  removeLevel(levelIndex: number) {\n    this.levelController.removeLevel(levelIndex);\n  }\n\n  /**\n   * @returns an array of levels (variants) sorted by HDCP-LEVEL, RESOLUTION (height), FRAME-RATE, CODECS, VIDEO-RANGE, and BANDWIDTH\n   */\n  get levels(): Level[] {\n    const levels = this.levelController.levels;\n    return levels ? levels : [];\n  }\n\n  /**\n   * Index of quality level (variant) currently played\n   */\n  get currentLevel(): number {\n    return this.streamController.currentLevel;\n  }\n\n  /**\n   * Set quality level index immediately. This will flush the current buffer to replace the quality asap. That means playback will interrupt at least shortly to re-buffer and re-sync eventually. Set to -1 for automatic level selection.\n   */\n  set currentLevel(newLevel: number) {\n    logger.log(`set currentLevel:${newLevel}`);\n    this.levelController.manualLevel = newLevel;\n    this.streamController.immediateLevelSwitch();\n  }\n\n  /**\n   * Index of next quality level loaded as scheduled by stream controller.\n   */\n  get nextLevel(): number {\n    return this.streamController.nextLevel;\n  }\n\n  /**\n   * Set quality level index for next loaded data.\n   * This will switch the video quality asap, without interrupting playback.\n   * May abort current loading of data, and flush parts of buffer (outside currently played fragment region).\n   * @param newLevel - Pass -1 for automatic level selection\n   */\n  set nextLevel(newLevel: number) {\n    logger.log(`set nextLevel:${newLevel}`);\n    this.levelController.manualLevel = newLevel;\n    this.streamController.nextLevelSwitch();\n  }\n\n  /**\n   * Return the quality level of the currently or last (of none is loaded currently) segment\n   */\n  get loadLevel(): number {\n    return this.levelController.level;\n  }\n\n  /**\n   * Set quality level index for next loaded data in a conservative way.\n   * This will switch the quality without flushing, but interrupt current loading.\n   * Thus the moment when the quality switch will appear in effect will only be after the already existing buffer.\n   * @param newLevel - Pass -1 for automatic level selection\n   */\n  set loadLevel(newLevel: number) {\n    logger.log(`set loadLevel:${newLevel}`);\n    this.levelController.manualLevel = newLevel;\n  }\n\n  /**\n   * get next quality level loaded\n   */\n  get nextLoadLevel(): number {\n    return this.levelController.nextLoadLevel;\n  }\n\n  /**\n   * Set quality level of next loaded segment in a fully \"non-destructive\" way.\n   * Same as `loadLevel` but will wait for next switch (until current loading is done).\n   */\n  set nextLoadLevel(level: number) {\n    this.levelController.nextLoadLevel = level;\n  }\n\n  /**\n   * Return \"first level\": like a default level, if not set,\n   * falls back to index of first level referenced in manifest\n   */\n  get firstLevel(): number {\n    return Math.max(this.levelController.firstLevel, this.minAutoLevel);\n  }\n\n  /**\n   * Sets \"first-level\", see getter.\n   */\n  set firstLevel(newLevel: number) {\n    logger.log(`set firstLevel:${newLevel}`);\n    this.levelController.firstLevel = newLevel;\n  }\n\n  /**\n   * Return the desired start level for the first fragment that will be loaded.\n   * The default value of -1 indicates automatic start level selection.\n   * Setting hls.nextAutoLevel without setting a startLevel will result in\n   * the nextAutoLevel value being used for one fragment load.\n   */\n  get startLevel(): number {\n    const startLevel = this.levelController.startLevel;\n    if (startLevel === -1 && this.abrController.forcedAutoLevel > -1) {\n      return this.abrController.forcedAutoLevel;\n    }\n    return startLevel;\n  }\n\n  /**\n   * set  start level (level of first fragment that will be played back)\n   * if not overrided by user, first level appearing in manifest will be used as start level\n   * if -1 : automatic start level selection, playback will start from level matching download bandwidth\n   * (determined from download of first segment)\n   */\n  set startLevel(newLevel: number) {\n    logger.log(`set startLevel:${newLevel}`);\n    // if not in automatic start level detection, ensure startLevel is greater than minAutoLevel\n    if (newLevel !== -1) {\n      newLevel = Math.max(newLevel, this.minAutoLevel);\n    }\n\n    this.levelController.startLevel = newLevel;\n  }\n\n  /**\n   * Whether level capping is enabled.\n   * Default value is set via `config.capLevelToPlayerSize`.\n   */\n  get capLevelToPlayerSize(): boolean {\n    return this.config.capLevelToPlayerSize;\n  }\n\n  /**\n   * Enables or disables level capping. If disabled after previously enabled, `nextLevelSwitch` will be immediately called.\n   */\n  set capLevelToPlayerSize(shouldStartCapping: boolean) {\n    const newCapLevelToPlayerSize = !!shouldStartCapping;\n\n    if (newCapLevelToPlayerSize !== this.config.capLevelToPlayerSize) {\n      if (newCapLevelToPlayerSize) {\n        this.capLevelController.startCapping(); // If capping occurs, nextLevelSwitch will happen based on size.\n      } else {\n        this.capLevelController.stopCapping();\n        this.autoLevelCapping = -1;\n        this.streamController.nextLevelSwitch(); // Now we're uncapped, get the next level asap.\n      }\n\n      this.config.capLevelToPlayerSize = newCapLevelToPlayerSize;\n    }\n  }\n\n  /**\n   * Capping/max level value that should be used by automatic level selection algorithm (`ABRController`)\n   */\n  get autoLevelCapping(): number {\n    return this._autoLevelCapping;\n  }\n\n  /**\n   * Returns the current bandwidth estimate in bits per second, when available. Otherwise, `NaN` is returned.\n   */\n  get bandwidthEstimate(): number {\n    const { bwEstimator } = this.abrController;\n    if (!bwEstimator) {\n      return NaN;\n    }\n    return bwEstimator.getEstimate();\n  }\n\n  set bandwidthEstimate(abrEwmaDefaultEstimate: number) {\n    this.abrController.resetEstimator(abrEwmaDefaultEstimate);\n  }\n\n  /**\n   * get time to first byte estimate\n   * @type {number}\n   */\n  get ttfbEstimate(): number {\n    const { bwEstimator } = this.abrController;\n    if (!bwEstimator) {\n      return NaN;\n    }\n    return bwEstimator.getEstimateTTFB();\n  }\n\n  /**\n   * Capping/max level value that should be used by automatic level selection algorithm (`ABRController`)\n   */\n  set autoLevelCapping(newLevel: number) {\n    if (this._autoLevelCapping !== newLevel) {\n      logger.log(`set autoLevelCapping:${newLevel}`);\n      this._autoLevelCapping = newLevel;\n      this.levelController.checkMaxAutoUpdated();\n    }\n  }\n\n  get maxHdcpLevel(): HdcpLevel {\n    return this._maxHdcpLevel;\n  }\n\n  set maxHdcpLevel(value: HdcpLevel) {\n    if (isHdcpLevel(value) && this._maxHdcpLevel !== value) {\n      this._maxHdcpLevel = value;\n      this.levelController.checkMaxAutoUpdated();\n    }\n  }\n\n  /**\n   * True when automatic level selection enabled\n   */\n  get autoLevelEnabled(): boolean {\n    return this.levelController.manualLevel === -1;\n  }\n\n  /**\n   * Level set manually (if any)\n   */\n  get manualLevel(): number {\n    return this.levelController.manualLevel;\n  }\n\n  /**\n   * min level selectable in auto mode according to config.minAutoBitrate\n   */\n  get minAutoLevel(): number {\n    const {\n      levels,\n      config: { minAutoBitrate },\n    } = this;\n    if (!levels) return 0;\n\n    const len = levels.length;\n    for (let i = 0; i < len; i++) {\n      if (levels[i].maxBitrate >= minAutoBitrate) {\n        return i;\n      }\n    }\n\n    return 0;\n  }\n\n  /**\n   * max level selectable in auto mode according to autoLevelCapping\n   */\n  get maxAutoLevel(): number {\n    const { levels, autoLevelCapping, maxHdcpLevel } = this;\n\n    let maxAutoLevel;\n    if (autoLevelCapping === -1 && levels?.length) {\n      maxAutoLevel = levels.length - 1;\n    } else {\n      maxAutoLevel = autoLevelCapping;\n    }\n\n    if (maxHdcpLevel) {\n      for (let i = maxAutoLevel; i--; ) {\n        const hdcpLevel = levels[i].attrs['HDCP-LEVEL'];\n        if (hdcpLevel && hdcpLevel <= maxHdcpLevel) {\n          return i;\n        }\n      }\n    }\n\n    return maxAutoLevel;\n  }\n\n  get firstAutoLevel(): number {\n    return this.abrController.firstAutoLevel;\n  }\n\n  /**\n   * next automatically selected quality level\n   */\n  get nextAutoLevel(): number {\n    return this.abrController.nextAutoLevel;\n  }\n\n  /**\n   * this setter is used to force next auto level.\n   * this is useful to force a switch down in auto mode:\n   * in case of load error on level N, hls.js can set nextAutoLevel to N-1 for example)\n   * forced value is valid for one fragment. upon successful frag loading at forced level,\n   * this value will be resetted to -1 by ABR controller.\n   */\n  set nextAutoLevel(nextLevel: number) {\n    this.abrController.nextAutoLevel = nextLevel;\n  }\n\n  /**\n   * get the datetime value relative to media.currentTime for the active level Program Date Time if present\n   */\n  public get playingDate(): Date | null {\n    return this.streamController.currentProgramDateTime;\n  }\n\n  public get mainForwardBufferInfo(): BufferInfo | null {\n    return this.streamController.getMainFwdBufferInfo();\n  }\n\n  /**\n   * Find and select the best matching audio track, making a level switch when a Group change is necessary.\n   * Updates `hls.config.audioPreference`. Returns the selected track, or null when no matching track is found.\n   */\n  public setAudioOption(\n    audioOption: MediaPlaylist | AudioSelectionOption | undefined,\n  ): MediaPlaylist | null {\n    return this.audioTrackController?.setAudioOption(audioOption);\n  }\n  /**\n   * Find and select the best matching subtitle track, making a level switch when a Group change is necessary.\n   * Updates `hls.config.subtitlePreference`. Returns the selected track, or null when no matching track is found.\n   */\n  public setSubtitleOption(\n    subtitleOption: MediaPlaylist | SubtitleSelectionOption | undefined,\n  ): MediaPlaylist | null {\n    this.subtitleTrackController?.setSubtitleOption(subtitleOption);\n    return null;\n  }\n\n  /**\n   * Get the complete list of audio tracks across all media groups\n   */\n  get allAudioTracks(): Array<MediaPlaylist> {\n    const audioTrackController = this.audioTrackController;\n    return audioTrackController ? audioTrackController.allAudioTracks : [];\n  }\n\n  /**\n   * Get the list of selectable audio tracks\n   */\n  get audioTracks(): Array<MediaPlaylist> {\n    const audioTrackController = this.audioTrackController;\n    return audioTrackController ? audioTrackController.audioTracks : [];\n  }\n\n  /**\n   * index of the selected audio track (index in audio track lists)\n   */\n  get audioTrack(): number {\n    const audioTrackController = this.audioTrackController;\n    return audioTrackController ? audioTrackController.audioTrack : -1;\n  }\n\n  /**\n   * selects an audio track, based on its index in audio track lists\n   */\n  set audioTrack(audioTrackId: number) {\n    const audioTrackController = this.audioTrackController;\n    if (audioTrackController) {\n      audioTrackController.audioTrack = audioTrackId;\n    }\n  }\n\n  /**\n   * get the complete list of subtitle tracks across all media groups\n   */\n  get allSubtitleTracks(): Array<MediaPlaylist> {\n    const subtitleTrackController = this.subtitleTrackController;\n    return subtitleTrackController\n      ? subtitleTrackController.allSubtitleTracks\n      : [];\n  }\n\n  /**\n   * get alternate subtitle tracks list from playlist\n   */\n  get subtitleTracks(): Array<MediaPlaylist> {\n    const subtitleTrackController = this.subtitleTrackController;\n    return subtitleTrackController\n      ? subtitleTrackController.subtitleTracks\n      : [];\n  }\n\n  /**\n   * index of the selected subtitle track (index in subtitle track lists)\n   */\n  get subtitleTrack(): number {\n    const subtitleTrackController = this.subtitleTrackController;\n    return subtitleTrackController ? subtitleTrackController.subtitleTrack : -1;\n  }\n\n  get media() {\n    return this._media;\n  }\n\n  /**\n   * select an subtitle track, based on its index in subtitle track lists\n   */\n  set subtitleTrack(subtitleTrackId: number) {\n    const subtitleTrackController = this.subtitleTrackController;\n    if (subtitleTrackController) {\n      subtitleTrackController.subtitleTrack = subtitleTrackId;\n    }\n  }\n\n  /**\n   * Whether subtitle display is enabled or not\n   */\n  get subtitleDisplay(): boolean {\n    const subtitleTrackController = this.subtitleTrackController;\n    return subtitleTrackController\n      ? subtitleTrackController.subtitleDisplay\n      : false;\n  }\n\n  /**\n   * Enable/disable subtitle display rendering\n   */\n  set subtitleDisplay(value: boolean) {\n    const subtitleTrackController = this.subtitleTrackController;\n    if (subtitleTrackController) {\n      subtitleTrackController.subtitleDisplay = value;\n    }\n  }\n\n  /**\n   * get mode for Low-Latency HLS loading\n   */\n  get lowLatencyMode(): boolean {\n    return this.config.lowLatencyMode;\n  }\n\n  /**\n   * Enable/disable Low-Latency HLS part playlist and segment loading, and start live streams at playlist PART-HOLD-BACK rather than HOLD-BACK.\n   */\n  set lowLatencyMode(mode: boolean) {\n    this.config.lowLatencyMode = mode;\n  }\n\n  /**\n   * Position (in seconds) of live sync point (ie edge of live position minus safety delay defined by ```hls.config.liveSyncDuration```)\n   * @returns null prior to loading live Playlist\n   */\n  get liveSyncPosition(): number | null {\n    return this.latencyController.liveSyncPosition;\n  }\n\n  /**\n   * Estimated position (in seconds) of live edge (ie edge of live playlist plus time sync playlist advanced)\n   * @returns 0 before first playlist is loaded\n   */\n  get latency(): number {\n    return this.latencyController.latency;\n  }\n\n  /**\n   * maximum distance from the edge before the player seeks forward to ```hls.liveSyncPosition```\n   * configured using ```liveMaxLatencyDurationCount``` (multiple of target duration) or ```liveMaxLatencyDuration```\n   * @returns 0 before first playlist is loaded\n   */\n  get maxLatency(): number {\n    return this.latencyController.maxLatency;\n  }\n\n  /**\n   * target distance from the edge as calculated by the latency controller\n   */\n  get targetLatency(): number | null {\n    return this.latencyController.targetLatency;\n  }\n\n  /**\n   * the rate at which the edge of the current live playlist is advancing or 1 if there is none\n   */\n  get drift(): number | null {\n    return this.latencyController.drift;\n  }\n\n  /**\n   * set to true when startLoad is called before MANIFEST_PARSED event\n   */\n  get forceStartLoad(): boolean {\n    return this.streamController.forceStartLoad;\n  }\n}\n\nexport type {\n  AudioSelectionOption,\n  SubtitleSelectionOption,\n  VideoSelectionOption,\n  MediaPlaylist,\n  ErrorDetails,\n  ErrorTypes,\n  Events,\n  Level,\n  HlsListeners,\n  HlsEventEmitter,\n  HlsConfig,\n  BufferInfo,\n  HdcpLevel,\n  AbrController,\n  AudioStreamController,\n  AudioTrackController,\n  BasePlaylistController,\n  BaseStreamController,\n  BufferController,\n  CapLevelController,\n  CMCDController,\n  ContentSteeringController,\n  EMEController,\n  ErrorController,\n  FPSController,\n  SubtitleTrackController,\n};\nexport type {\n  ComponentAPI,\n  AbrComponentAPI,\n  NetworkComponentAPI,\n} from './types/component-api';\nexport type {\n  ABRControllerConfig,\n  BufferControllerConfig,\n  CapLevelControllerConfig,\n  CMCDControllerConfig,\n  EMEControllerConfig,\n  DRMSystemsConfiguration,\n  DRMSystemOptions,\n  FPSControllerConfig,\n  FragmentLoaderConfig,\n  FragmentLoaderConstructor,\n  HlsLoadPolicies,\n  LevelControllerConfig,\n  LoaderConfig,\n  LoadPolicy,\n  MP4RemuxerConfig,\n  PlaylistLoaderConfig,\n  PlaylistLoaderConstructor,\n  RetryConfig,\n  SelectionPreferences,\n  StreamControllerConfig,\n  LatencyControllerConfig,\n  MetadataControllerConfig,\n  TimelineControllerConfig,\n  TSDemuxerConfig,\n} from './config';\nexport type { MediaKeySessionContext } from './controller/eme-controller';\nexport type { ILogger } from './utils/logger';\nexport type {\n  PathwayClone,\n  SteeringManifest,\n  UriReplacement,\n} from './controller/content-steering-controller';\nexport type { SubtitleStreamController } from './controller/subtitle-stream-controller';\nexport type { TimelineController } from './controller/timeline-controller';\nexport type { CuesInterface } from './utils/cues';\nexport type {\n  MediaKeyFunc,\n  KeySystems,\n  KeySystemFormats,\n} from './utils/mediakeys-helper';\nexport type { DateRange } from './loader/date-range';\nexport type { LoadStats } from './loader/load-stats';\nexport type { LevelKey } from './loader/level-key';\nexport type { LevelDetails } from './loader/level-details';\nexport type { SourceBufferName } from './types/buffer';\nexport type {\n  MetadataSample,\n  MetadataSchema,\n  UserdataSample,\n} from './types/demuxer';\nexport type {\n  HlsSkip,\n  HlsUrlParameters,\n  LevelAttributes,\n  LevelParsed,\n  VariableMap,\n} from './types/level';\nexport type { MediaDecodingInfo } from './utils/mediacapabilities-helper';\nexport type {\n  PlaylistLevelType,\n  HlsChunkPerformanceTiming,\n  HlsPerformanceTiming,\n  HlsProgressivePerformanceTiming,\n  PlaylistContextType,\n  PlaylistLoaderContext,\n  FragmentLoaderContext,\n  Loader,\n  LoaderStats,\n  LoaderContext,\n  LoaderResponse,\n  LoaderConfiguration,\n  LoaderCallbacks,\n  LoaderOnProgress,\n  LoaderOnAbort,\n  LoaderOnError,\n  LoaderOnSuccess,\n  LoaderOnTimeout,\n} from './types/loader';\nexport type {\n  MediaAttributes,\n  MediaPlaylistType,\n  MainPlaylistType,\n  AudioPlaylistType,\n  SubtitlePlaylistType,\n} from './types/media-playlist';\nexport type { Track, TrackSet } from './types/track';\nexport type { ChunkMetadata } from './types/transmuxer';\nexport type {\n  BaseSegment,\n  Fragment,\n  Part,\n  ElementaryStreams,\n  ElementaryStreamTypes,\n  ElementaryStreamInfo,\n} from './loader/fragment';\nexport type {\n  TrackLoadingData,\n  TrackLoadedData,\n  AudioTrackLoadedData,\n  AudioTracksUpdatedData,\n  AudioTrackSwitchedData,\n  AudioTrackSwitchingData,\n  BackBufferData,\n  BufferAppendedData,\n  BufferAppendingData,\n  BufferCodecsData,\n  BufferCreatedData,\n  BufferEOSData,\n  BufferFlushedData,\n  BufferFlushingData,\n  CuesParsedData,\n  ErrorData,\n  FPSDropData,\n  FPSDropLevelCappingData,\n  FragBufferedData,\n  FragChangedData,\n  FragDecryptedData,\n  FragLoadedData,\n  FragLoadEmergencyAbortedData,\n  FragLoadingData,\n  FragParsedData,\n  FragParsingInitSegmentData,\n  FragParsingMetadataData,\n  FragParsingUserdataData,\n  InitPTSFoundData,\n  KeyLoadedData,\n  KeyLoadingData,\n  LevelLoadedData,\n  LevelLoadingData,\n  LevelPTSUpdatedData,\n  LevelsUpdatedData,\n  LevelSwitchedData,\n  LevelSwitchingData,\n  LevelUpdatedData,\n  LiveBackBufferData,\n  ContentSteeringOptions,\n  ManifestLoadedData,\n  ManifestLoadingData,\n  ManifestParsedData,\n  MediaAttachedData,\n  MediaAttachingData,\n  NonNativeTextTrack,\n  NonNativeTextTracksData,\n  SteeringManifestLoadedData,\n  SubtitleFragProcessedData,\n  SubtitleTrackLoadedData,\n  SubtitleTracksUpdatedData,\n  SubtitleTrackSwitchData,\n} from './types/events';\nexport type {\n  NetworkErrorAction,\n  ErrorActionFlags,\n  IErrorAction,\n} from './controller/error-controller';\nexport type { AttrList } from './utils/attr-list';\n", "import Hls from 'hls.js'\nimport Plyr from 'plyr'\n\nexport default ({\n  src,\n  controls = [\n    'play-large',\n    'play',\n    'progress',\n    'current-time',\n    'duration',\n    // 'pip',\n    // 'airplay',\n    'volume',\n    'mute',\n    'captions',\n    'fullscreen',\n  ],\n  shortcuts = false,\n  autoplay = false,\n  key = false,\n  title,\n  subtitle,\n}) => ({\n  src,\n  controls,\n  shortcuts,\n  autoplay,\n  key,\n  player: null,\n  title,\n  subtitle,\n  init() {\n    const videoPlayer = document.querySelector('video#player')\n\n    this.player = new Plyr(videoPlayer, {\n      controls: this.controls,\n      captions: { active: false, update: true, language: 'en' },\n      fullscreen: { iosNative: true },\n      keyboard: { focused: true, global: this.shortcuts },\n      mediaMetadata: { title: this.title },\n    })\n\n    if (Hls.isSupported()) {\n      const hls = new Hls({ autoStartLoad: false })\n      hls.loadSource(this.src)\n      hls.attachMedia(videoPlayer)\n\n      videoPlayer.addEventListener(\n        'play',\n        () => {\n          hls.startLoad()\n        },\n        { once: true }\n      )\n    } else {\n      videoPlayer.src = this.src\n    }\n  },\n})\n", "const project = () => ({\n  getPostIndexFromUrl: () =>\n    window?.location?.href?.match(/(\\d+)$/g)?.[0] || '1',\n})\n\nexport default project\n", "export default function QuestHandler() {\n  return {\n    submitForm: (url) => async (e) => {\n      const formData = new FormData(e.target)\n      // const challenge = formData.get(\"challenge\")\n      try {\n        const response = await fetch(url, {\n          method: 'POST',\n          body: formData,\n        })\n\n        response.ok\n          ? location.reload()\n          : console.log('Request failed with status:', response.status)\n      } catch (err) {\n        console.log(err)\n      }\n    },\n  }\n}\n", "// platform = facebook/twitter\nconst SOCIAL_LINKS = {\n  facebook: 'https://www.facebook.com/sharer/sharer.php',\n  twitter: 'https://twitter.com/intent/tweet',\n}\nexport default ({ platform = 'facebook', projectName, inviteUrl }) => ({\n  shareLink() {\n    const url = new URL(SOCIAL_LINKS[platform])\n    const params = new URLSearchParams()\n    params.append(platform === 'facebook' ? 'u' : 'url', inviteUrl)\n    params.append('text', `Subscribe to Loor and help me fund ${projectName}!`)\n    url.search = params\n\n    return url.toString()\n  },\n})\n", "export const Sortable = {\n  mounted() {\n    this.el.addEventListener('dragstart', (e) => {\n      const id = e.target.dataset.id\n      e.dataTransfer.effectAllowed = 'move'\n      e.dataTransfer.setData('text/html', e.target.outerHTML)\n      this.pushEvent('start_drag', { id: id })\n    })\n\n    this.el.addEventListener('dragover', (e) => {\n      e.preventDefault()\n      e.dataTransfer.dropEffect = 'move'\n    })\n\n    this.el.addEventListener('dragenter', (e) => {\n      e.preventDefault()\n      e.target.classList.add('bg-blue-50', 'border-blue-300')\n    })\n\n    this.el.addEventListener('dragleave', (e) => {\n      e.target.classList.remove('bg-blue-50', 'border-blue-300')\n    })\n\n    this.el.addEventListener('drop', (e) => {\n      e.preventDefault()\n      e.target.classList.remove('bg-blue-50', 'border-blue-300')\n      \n      const targetId = e.target.closest('[data-id]')?.dataset.id\n      if (targetId) {\n        this.pushEvent('drop', { target_id: targetId })\n      }\n    })\n\n    this.el.addEventListener('dragend', (e) => {\n      // Clean up any remaining styling\n      const items = this.el.parentElement.querySelectorAll('[data-id]')\n      items.forEach(item => {\n        item.classList.remove('bg-blue-50', 'border-blue-300')\n      })\n      \n      this.pushEvent('cancel_drag', {})\n    })\n  }\n}", "/**\n * SSR Window 4.0.2\n * Better handling for window object in SSR environment\n * https://github.com/nolimits4web/ssr-window\n *\n * Copyright 2021, Vladimir Kharlampidi\n *\n * Licensed under MIT\n *\n * Released on: December 13, 2021\n */\n/* eslint-disable no-param-reassign */\nfunction isObject(obj) {\n    return (obj !== null &&\n        typeof obj === 'object' &&\n        'constructor' in obj &&\n        obj.constructor === Object);\n}\nfunction extend(target = {}, src = {}) {\n    Object.keys(src).forEach((key) => {\n        if (typeof target[key] === 'undefined')\n            target[key] = src[key];\n        else if (isObject(src[key]) &&\n            isObject(target[key]) &&\n            Object.keys(src[key]).length > 0) {\n            extend(target[key], src[key]);\n        }\n    });\n}\n\nconst ssrDocument = {\n    body: {},\n    addEventListener() { },\n    removeEventListener() { },\n    activeElement: {\n        blur() { },\n        nodeName: '',\n    },\n    querySelector() {\n        return null;\n    },\n    querySelectorAll() {\n        return [];\n    },\n    getElementById() {\n        return null;\n    },\n    createEvent() {\n        return {\n            initEvent() { },\n        };\n    },\n    createElement() {\n        return {\n            children: [],\n            childNodes: [],\n            style: {},\n            setAttribute() { },\n            getElementsByTagName() {\n                return [];\n            },\n        };\n    },\n    createElementNS() {\n        return {};\n    },\n    importNode() {\n        return null;\n    },\n    location: {\n        hash: '',\n        host: '',\n        hostname: '',\n        href: '',\n        origin: '',\n        pathname: '',\n        protocol: '',\n        search: '',\n    },\n};\nfunction getDocument() {\n    const doc = typeof document !== 'undefined' ? document : {};\n    extend(doc, ssrDocument);\n    return doc;\n}\n\nconst ssrWindow = {\n    document: ssrDocument,\n    navigator: {\n        userAgent: '',\n    },\n    location: {\n        hash: '',\n        host: '',\n        hostname: '',\n        href: '',\n        origin: '',\n        pathname: '',\n        protocol: '',\n        search: '',\n    },\n    history: {\n        replaceState() { },\n        pushState() { },\n        go() { },\n        back() { },\n    },\n    CustomEvent: function CustomEvent() {\n        return this;\n    },\n    addEventListener() { },\n    removeEventListener() { },\n    getComputedStyle() {\n        return {\n            getPropertyValue() {\n                return '';\n            },\n        };\n    },\n    Image() { },\n    Date() { },\n    screen: {},\n    setTimeout() { },\n    clearTimeout() { },\n    matchMedia() {\n        return {};\n    },\n    requestAnimationFrame(callback) {\n        if (typeof setTimeout === 'undefined') {\n            callback();\n            return null;\n        }\n        return setTimeout(callback, 0);\n    },\n    cancelAnimationFrame(id) {\n        if (typeof setTimeout === 'undefined') {\n            return;\n        }\n        clearTimeout(id);\n    },\n};\nfunction getWindow() {\n    const win = typeof window !== 'undefined' ? window : {};\n    extend(win, ssrWindow);\n    return win;\n}\n\nexport { extend, getDocument, getWindow, ssrDocument, ssrWindow };\n", "/**\n * Dom7 4.0.4\n * Minimalistic JavaScript library for DOM manipulation, with a jQuery-compatible API\n * https://framework7.io/docs/dom7.html\n *\n * Copyright 2022, Vladimir Kharlampidi\n *\n * Licensed under MIT\n *\n * Released on: January 11, 2022\n */\nimport { getWindow, getDocument } from 'ssr-window';\n\n/* eslint-disable no-proto */\nfunction makeReactive(obj) {\n  const proto = obj.__proto__;\n  Object.defineProperty(obj, '__proto__', {\n    get() {\n      return proto;\n    },\n\n    set(value) {\n      proto.__proto__ = value;\n    }\n\n  });\n}\n\nclass Dom7 extends Array {\n  constructor(items) {\n    if (typeof items === 'number') {\n      super(items);\n    } else {\n      super(...(items || []));\n      makeReactive(this);\n    }\n  }\n\n}\n\nfunction arrayFlat(arr = []) {\n  const res = [];\n  arr.forEach(el => {\n    if (Array.isArray(el)) {\n      res.push(...arrayFlat(el));\n    } else {\n      res.push(el);\n    }\n  });\n  return res;\n}\nfunction arrayFilter(arr, callback) {\n  return Array.prototype.filter.call(arr, callback);\n}\nfunction arrayUnique(arr) {\n  const uniqueArray = [];\n\n  for (let i = 0; i < arr.length; i += 1) {\n    if (uniqueArray.indexOf(arr[i]) === -1) uniqueArray.push(arr[i]);\n  }\n\n  return uniqueArray;\n}\nfunction toCamelCase(string) {\n  return string.toLowerCase().replace(/-(.)/g, (match, group) => group.toUpperCase());\n}\n\n// eslint-disable-next-line\n\nfunction qsa(selector, context) {\n  if (typeof selector !== 'string') {\n    return [selector];\n  }\n\n  const a = [];\n  const res = context.querySelectorAll(selector);\n\n  for (let i = 0; i < res.length; i += 1) {\n    a.push(res[i]);\n  }\n\n  return a;\n}\n\nfunction $(selector, context) {\n  const window = getWindow();\n  const document = getDocument();\n  let arr = [];\n\n  if (!context && selector instanceof Dom7) {\n    return selector;\n  }\n\n  if (!selector) {\n    return new Dom7(arr);\n  }\n\n  if (typeof selector === 'string') {\n    const html = selector.trim();\n\n    if (html.indexOf('<') >= 0 && html.indexOf('>') >= 0) {\n      let toCreate = 'div';\n      if (html.indexOf('<li') === 0) toCreate = 'ul';\n      if (html.indexOf('<tr') === 0) toCreate = 'tbody';\n      if (html.indexOf('<td') === 0 || html.indexOf('<th') === 0) toCreate = 'tr';\n      if (html.indexOf('<tbody') === 0) toCreate = 'table';\n      if (html.indexOf('<option') === 0) toCreate = 'select';\n      const tempParent = document.createElement(toCreate);\n      tempParent.innerHTML = html;\n\n      for (let i = 0; i < tempParent.childNodes.length; i += 1) {\n        arr.push(tempParent.childNodes[i]);\n      }\n    } else {\n      arr = qsa(selector.trim(), context || document);\n    } // arr = qsa(selector, document);\n\n  } else if (selector.nodeType || selector === window || selector === document) {\n    arr.push(selector);\n  } else if (Array.isArray(selector)) {\n    if (selector instanceof Dom7) return selector;\n    arr = selector;\n  }\n\n  return new Dom7(arrayUnique(arr));\n}\n\n$.fn = Dom7.prototype;\n\n// eslint-disable-next-line\n\nfunction addClass(...classes) {\n  const classNames = arrayFlat(classes.map(c => c.split(' ')));\n  this.forEach(el => {\n    el.classList.add(...classNames);\n  });\n  return this;\n}\n\nfunction removeClass(...classes) {\n  const classNames = arrayFlat(classes.map(c => c.split(' ')));\n  this.forEach(el => {\n    el.classList.remove(...classNames);\n  });\n  return this;\n}\n\nfunction toggleClass(...classes) {\n  const classNames = arrayFlat(classes.map(c => c.split(' ')));\n  this.forEach(el => {\n    classNames.forEach(className => {\n      el.classList.toggle(className);\n    });\n  });\n}\n\nfunction hasClass(...classes) {\n  const classNames = arrayFlat(classes.map(c => c.split(' ')));\n  return arrayFilter(this, el => {\n    return classNames.filter(className => el.classList.contains(className)).length > 0;\n  }).length > 0;\n}\n\nfunction attr(attrs, value) {\n  if (arguments.length === 1 && typeof attrs === 'string') {\n    // Get attr\n    if (this[0]) return this[0].getAttribute(attrs);\n    return undefined;\n  } // Set attrs\n\n\n  for (let i = 0; i < this.length; i += 1) {\n    if (arguments.length === 2) {\n      // String\n      this[i].setAttribute(attrs, value);\n    } else {\n      // Object\n      for (const attrName in attrs) {\n        this[i][attrName] = attrs[attrName];\n        this[i].setAttribute(attrName, attrs[attrName]);\n      }\n    }\n  }\n\n  return this;\n}\n\nfunction removeAttr(attr) {\n  for (let i = 0; i < this.length; i += 1) {\n    this[i].removeAttribute(attr);\n  }\n\n  return this;\n}\n\nfunction prop(props, value) {\n  if (arguments.length === 1 && typeof props === 'string') {\n    // Get prop\n    if (this[0]) return this[0][props];\n  } else {\n    // Set props\n    for (let i = 0; i < this.length; i += 1) {\n      if (arguments.length === 2) {\n        // String\n        this[i][props] = value;\n      } else {\n        // Object\n        for (const propName in props) {\n          this[i][propName] = props[propName];\n        }\n      }\n    }\n\n    return this;\n  }\n\n  return this;\n}\n\nfunction data(key, value) {\n  let el;\n\n  if (typeof value === 'undefined') {\n    el = this[0];\n    if (!el) return undefined; // Get value\n\n    if (el.dom7ElementDataStorage && key in el.dom7ElementDataStorage) {\n      return el.dom7ElementDataStorage[key];\n    }\n\n    const dataKey = el.getAttribute(`data-${key}`);\n\n    if (dataKey) {\n      return dataKey;\n    }\n\n    return undefined;\n  } // Set value\n\n\n  for (let i = 0; i < this.length; i += 1) {\n    el = this[i];\n    if (!el.dom7ElementDataStorage) el.dom7ElementDataStorage = {};\n    el.dom7ElementDataStorage[key] = value;\n  }\n\n  return this;\n}\n\nfunction removeData(key) {\n  for (let i = 0; i < this.length; i += 1) {\n    const el = this[i];\n\n    if (el.dom7ElementDataStorage && el.dom7ElementDataStorage[key]) {\n      el.dom7ElementDataStorage[key] = null;\n      delete el.dom7ElementDataStorage[key];\n    }\n  }\n}\n\nfunction dataset() {\n  const el = this[0];\n  if (!el) return undefined;\n  const dataset = {}; // eslint-disable-line\n\n  if (el.dataset) {\n    for (const dataKey in el.dataset) {\n      dataset[dataKey] = el.dataset[dataKey];\n    }\n  } else {\n    for (let i = 0; i < el.attributes.length; i += 1) {\n      const attr = el.attributes[i];\n\n      if (attr.name.indexOf('data-') >= 0) {\n        dataset[toCamelCase(attr.name.split('data-')[1])] = attr.value;\n      }\n    }\n  }\n\n  for (const key in dataset) {\n    if (dataset[key] === 'false') dataset[key] = false;else if (dataset[key] === 'true') dataset[key] = true;else if (parseFloat(dataset[key]) === dataset[key] * 1) dataset[key] *= 1;\n  }\n\n  return dataset;\n}\n\nfunction val(value) {\n  if (typeof value === 'undefined') {\n    // get value\n    const el = this[0];\n    if (!el) return undefined;\n\n    if (el.multiple && el.nodeName.toLowerCase() === 'select') {\n      const values = [];\n\n      for (let i = 0; i < el.selectedOptions.length; i += 1) {\n        values.push(el.selectedOptions[i].value);\n      }\n\n      return values;\n    }\n\n    return el.value;\n  } // set value\n\n\n  for (let i = 0; i < this.length; i += 1) {\n    const el = this[i];\n\n    if (Array.isArray(value) && el.multiple && el.nodeName.toLowerCase() === 'select') {\n      for (let j = 0; j < el.options.length; j += 1) {\n        el.options[j].selected = value.indexOf(el.options[j].value) >= 0;\n      }\n    } else {\n      el.value = value;\n    }\n  }\n\n  return this;\n}\n\nfunction value(value) {\n  return this.val(value);\n}\n\nfunction transform(transform) {\n  for (let i = 0; i < this.length; i += 1) {\n    this[i].style.transform = transform;\n  }\n\n  return this;\n}\n\nfunction transition(duration) {\n  for (let i = 0; i < this.length; i += 1) {\n    this[i].style.transitionDuration = typeof duration !== 'string' ? `${duration}ms` : duration;\n  }\n\n  return this;\n}\n\nfunction on(...args) {\n  let [eventType, targetSelector, listener, capture] = args;\n\n  if (typeof args[1] === 'function') {\n    [eventType, listener, capture] = args;\n    targetSelector = undefined;\n  }\n\n  if (!capture) capture = false;\n\n  function handleLiveEvent(e) {\n    const target = e.target;\n    if (!target) return;\n    const eventData = e.target.dom7EventData || [];\n\n    if (eventData.indexOf(e) < 0) {\n      eventData.unshift(e);\n    }\n\n    if ($(target).is(targetSelector)) listener.apply(target, eventData);else {\n      const parents = $(target).parents(); // eslint-disable-line\n\n      for (let k = 0; k < parents.length; k += 1) {\n        if ($(parents[k]).is(targetSelector)) listener.apply(parents[k], eventData);\n      }\n    }\n  }\n\n  function handleEvent(e) {\n    const eventData = e && e.target ? e.target.dom7EventData || [] : [];\n\n    if (eventData.indexOf(e) < 0) {\n      eventData.unshift(e);\n    }\n\n    listener.apply(this, eventData);\n  }\n\n  const events = eventType.split(' ');\n  let j;\n\n  for (let i = 0; i < this.length; i += 1) {\n    const el = this[i];\n\n    if (!targetSelector) {\n      for (j = 0; j < events.length; j += 1) {\n        const event = events[j];\n        if (!el.dom7Listeners) el.dom7Listeners = {};\n        if (!el.dom7Listeners[event]) el.dom7Listeners[event] = [];\n        el.dom7Listeners[event].push({\n          listener,\n          proxyListener: handleEvent\n        });\n        el.addEventListener(event, handleEvent, capture);\n      }\n    } else {\n      // Live events\n      for (j = 0; j < events.length; j += 1) {\n        const event = events[j];\n        if (!el.dom7LiveListeners) el.dom7LiveListeners = {};\n        if (!el.dom7LiveListeners[event]) el.dom7LiveListeners[event] = [];\n        el.dom7LiveListeners[event].push({\n          listener,\n          proxyListener: handleLiveEvent\n        });\n        el.addEventListener(event, handleLiveEvent, capture);\n      }\n    }\n  }\n\n  return this;\n}\n\nfunction off(...args) {\n  let [eventType, targetSelector, listener, capture] = args;\n\n  if (typeof args[1] === 'function') {\n    [eventType, listener, capture] = args;\n    targetSelector = undefined;\n  }\n\n  if (!capture) capture = false;\n  const events = eventType.split(' ');\n\n  for (let i = 0; i < events.length; i += 1) {\n    const event = events[i];\n\n    for (let j = 0; j < this.length; j += 1) {\n      const el = this[j];\n      let handlers;\n\n      if (!targetSelector && el.dom7Listeners) {\n        handlers = el.dom7Listeners[event];\n      } else if (targetSelector && el.dom7LiveListeners) {\n        handlers = el.dom7LiveListeners[event];\n      }\n\n      if (handlers && handlers.length) {\n        for (let k = handlers.length - 1; k >= 0; k -= 1) {\n          const handler = handlers[k];\n\n          if (listener && handler.listener === listener) {\n            el.removeEventListener(event, handler.proxyListener, capture);\n            handlers.splice(k, 1);\n          } else if (listener && handler.listener && handler.listener.dom7proxy && handler.listener.dom7proxy === listener) {\n            el.removeEventListener(event, handler.proxyListener, capture);\n            handlers.splice(k, 1);\n          } else if (!listener) {\n            el.removeEventListener(event, handler.proxyListener, capture);\n            handlers.splice(k, 1);\n          }\n        }\n      }\n    }\n  }\n\n  return this;\n}\n\nfunction once(...args) {\n  const dom = this;\n  let [eventName, targetSelector, listener, capture] = args;\n\n  if (typeof args[1] === 'function') {\n    [eventName, listener, capture] = args;\n    targetSelector = undefined;\n  }\n\n  function onceHandler(...eventArgs) {\n    listener.apply(this, eventArgs);\n    dom.off(eventName, targetSelector, onceHandler, capture);\n\n    if (onceHandler.dom7proxy) {\n      delete onceHandler.dom7proxy;\n    }\n  }\n\n  onceHandler.dom7proxy = listener;\n  return dom.on(eventName, targetSelector, onceHandler, capture);\n}\n\nfunction trigger(...args) {\n  const window = getWindow();\n  const events = args[0].split(' ');\n  const eventData = args[1];\n\n  for (let i = 0; i < events.length; i += 1) {\n    const event = events[i];\n\n    for (let j = 0; j < this.length; j += 1) {\n      const el = this[j];\n\n      if (window.CustomEvent) {\n        const evt = new window.CustomEvent(event, {\n          detail: eventData,\n          bubbles: true,\n          cancelable: true\n        });\n        el.dom7EventData = args.filter((data, dataIndex) => dataIndex > 0);\n        el.dispatchEvent(evt);\n        el.dom7EventData = [];\n        delete el.dom7EventData;\n      }\n    }\n  }\n\n  return this;\n}\n\nfunction transitionEnd(callback) {\n  const dom = this;\n\n  function fireCallBack(e) {\n    if (e.target !== this) return;\n    callback.call(this, e);\n    dom.off('transitionend', fireCallBack);\n  }\n\n  if (callback) {\n    dom.on('transitionend', fireCallBack);\n  }\n\n  return this;\n}\n\nfunction animationEnd(callback) {\n  const dom = this;\n\n  function fireCallBack(e) {\n    if (e.target !== this) return;\n    callback.call(this, e);\n    dom.off('animationend', fireCallBack);\n  }\n\n  if (callback) {\n    dom.on('animationend', fireCallBack);\n  }\n\n  return this;\n}\n\nfunction width() {\n  const window = getWindow();\n\n  if (this[0] === window) {\n    return window.innerWidth;\n  }\n\n  if (this.length > 0) {\n    return parseFloat(this.css('width'));\n  }\n\n  return null;\n}\n\nfunction outerWidth(includeMargins) {\n  if (this.length > 0) {\n    if (includeMargins) {\n      const styles = this.styles();\n      return this[0].offsetWidth + parseFloat(styles.getPropertyValue('margin-right')) + parseFloat(styles.getPropertyValue('margin-left'));\n    }\n\n    return this[0].offsetWidth;\n  }\n\n  return null;\n}\n\nfunction height() {\n  const window = getWindow();\n\n  if (this[0] === window) {\n    return window.innerHeight;\n  }\n\n  if (this.length > 0) {\n    return parseFloat(this.css('height'));\n  }\n\n  return null;\n}\n\nfunction outerHeight(includeMargins) {\n  if (this.length > 0) {\n    if (includeMargins) {\n      const styles = this.styles();\n      return this[0].offsetHeight + parseFloat(styles.getPropertyValue('margin-top')) + parseFloat(styles.getPropertyValue('margin-bottom'));\n    }\n\n    return this[0].offsetHeight;\n  }\n\n  return null;\n}\n\nfunction offset() {\n  if (this.length > 0) {\n    const window = getWindow();\n    const document = getDocument();\n    const el = this[0];\n    const box = el.getBoundingClientRect();\n    const body = document.body;\n    const clientTop = el.clientTop || body.clientTop || 0;\n    const clientLeft = el.clientLeft || body.clientLeft || 0;\n    const scrollTop = el === window ? window.scrollY : el.scrollTop;\n    const scrollLeft = el === window ? window.scrollX : el.scrollLeft;\n    return {\n      top: box.top + scrollTop - clientTop,\n      left: box.left + scrollLeft - clientLeft\n    };\n  }\n\n  return null;\n}\n\nfunction hide() {\n  for (let i = 0; i < this.length; i += 1) {\n    this[i].style.display = 'none';\n  }\n\n  return this;\n}\n\nfunction show() {\n  const window = getWindow();\n\n  for (let i = 0; i < this.length; i += 1) {\n    const el = this[i];\n\n    if (el.style.display === 'none') {\n      el.style.display = '';\n    }\n\n    if (window.getComputedStyle(el, null).getPropertyValue('display') === 'none') {\n      // Still not visible\n      el.style.display = 'block';\n    }\n  }\n\n  return this;\n}\n\nfunction styles() {\n  const window = getWindow();\n  if (this[0]) return window.getComputedStyle(this[0], null);\n  return {};\n}\n\nfunction css(props, value) {\n  const window = getWindow();\n  let i;\n\n  if (arguments.length === 1) {\n    if (typeof props === 'string') {\n      // .css('width')\n      if (this[0]) return window.getComputedStyle(this[0], null).getPropertyValue(props);\n    } else {\n      // .css({ width: '100px' })\n      for (i = 0; i < this.length; i += 1) {\n        for (const prop in props) {\n          this[i].style[prop] = props[prop];\n        }\n      }\n\n      return this;\n    }\n  }\n\n  if (arguments.length === 2 && typeof props === 'string') {\n    // .css('width', '100px')\n    for (i = 0; i < this.length; i += 1) {\n      this[i].style[props] = value;\n    }\n\n    return this;\n  }\n\n  return this;\n}\n\nfunction each(callback) {\n  if (!callback) return this;\n  this.forEach((el, index) => {\n    callback.apply(el, [el, index]);\n  });\n  return this;\n}\n\nfunction filter(callback) {\n  const result = arrayFilter(this, callback);\n  return $(result);\n}\n\nfunction html(html) {\n  if (typeof html === 'undefined') {\n    return this[0] ? this[0].innerHTML : null;\n  }\n\n  for (let i = 0; i < this.length; i += 1) {\n    this[i].innerHTML = html;\n  }\n\n  return this;\n}\n\nfunction text(text) {\n  if (typeof text === 'undefined') {\n    return this[0] ? this[0].textContent.trim() : null;\n  }\n\n  for (let i = 0; i < this.length; i += 1) {\n    this[i].textContent = text;\n  }\n\n  return this;\n}\n\nfunction is(selector) {\n  const window = getWindow();\n  const document = getDocument();\n  const el = this[0];\n  let compareWith;\n  let i;\n  if (!el || typeof selector === 'undefined') return false;\n\n  if (typeof selector === 'string') {\n    if (el.matches) return el.matches(selector);\n    if (el.webkitMatchesSelector) return el.webkitMatchesSelector(selector);\n    if (el.msMatchesSelector) return el.msMatchesSelector(selector);\n    compareWith = $(selector);\n\n    for (i = 0; i < compareWith.length; i += 1) {\n      if (compareWith[i] === el) return true;\n    }\n\n    return false;\n  }\n\n  if (selector === document) {\n    return el === document;\n  }\n\n  if (selector === window) {\n    return el === window;\n  }\n\n  if (selector.nodeType || selector instanceof Dom7) {\n    compareWith = selector.nodeType ? [selector] : selector;\n\n    for (i = 0; i < compareWith.length; i += 1) {\n      if (compareWith[i] === el) return true;\n    }\n\n    return false;\n  }\n\n  return false;\n}\n\nfunction index() {\n  let child = this[0];\n  let i;\n\n  if (child) {\n    i = 0; // eslint-disable-next-line\n\n    while ((child = child.previousSibling) !== null) {\n      if (child.nodeType === 1) i += 1;\n    }\n\n    return i;\n  }\n\n  return undefined;\n}\n\nfunction eq(index) {\n  if (typeof index === 'undefined') return this;\n  const length = this.length;\n\n  if (index > length - 1) {\n    return $([]);\n  }\n\n  if (index < 0) {\n    const returnIndex = length + index;\n    if (returnIndex < 0) return $([]);\n    return $([this[returnIndex]]);\n  }\n\n  return $([this[index]]);\n}\n\nfunction append(...els) {\n  let newChild;\n  const document = getDocument();\n\n  for (let k = 0; k < els.length; k += 1) {\n    newChild = els[k];\n\n    for (let i = 0; i < this.length; i += 1) {\n      if (typeof newChild === 'string') {\n        const tempDiv = document.createElement('div');\n        tempDiv.innerHTML = newChild;\n\n        while (tempDiv.firstChild) {\n          this[i].appendChild(tempDiv.firstChild);\n        }\n      } else if (newChild instanceof Dom7) {\n        for (let j = 0; j < newChild.length; j += 1) {\n          this[i].appendChild(newChild[j]);\n        }\n      } else {\n        this[i].appendChild(newChild);\n      }\n    }\n  }\n\n  return this;\n}\n\nfunction appendTo(parent) {\n  $(parent).append(this);\n  return this;\n}\n\nfunction prepend(newChild) {\n  const document = getDocument();\n  let i;\n  let j;\n\n  for (i = 0; i < this.length; i += 1) {\n    if (typeof newChild === 'string') {\n      const tempDiv = document.createElement('div');\n      tempDiv.innerHTML = newChild;\n\n      for (j = tempDiv.childNodes.length - 1; j >= 0; j -= 1) {\n        this[i].insertBefore(tempDiv.childNodes[j], this[i].childNodes[0]);\n      }\n    } else if (newChild instanceof Dom7) {\n      for (j = 0; j < newChild.length; j += 1) {\n        this[i].insertBefore(newChild[j], this[i].childNodes[0]);\n      }\n    } else {\n      this[i].insertBefore(newChild, this[i].childNodes[0]);\n    }\n  }\n\n  return this;\n}\n\nfunction prependTo(parent) {\n  $(parent).prepend(this);\n  return this;\n}\n\nfunction insertBefore(selector) {\n  const before = $(selector);\n\n  for (let i = 0; i < this.length; i += 1) {\n    if (before.length === 1) {\n      before[0].parentNode.insertBefore(this[i], before[0]);\n    } else if (before.length > 1) {\n      for (let j = 0; j < before.length; j += 1) {\n        before[j].parentNode.insertBefore(this[i].cloneNode(true), before[j]);\n      }\n    }\n  }\n}\n\nfunction insertAfter(selector) {\n  const after = $(selector);\n\n  for (let i = 0; i < this.length; i += 1) {\n    if (after.length === 1) {\n      after[0].parentNode.insertBefore(this[i], after[0].nextSibling);\n    } else if (after.length > 1) {\n      for (let j = 0; j < after.length; j += 1) {\n        after[j].parentNode.insertBefore(this[i].cloneNode(true), after[j].nextSibling);\n      }\n    }\n  }\n}\n\nfunction next(selector) {\n  if (this.length > 0) {\n    if (selector) {\n      if (this[0].nextElementSibling && $(this[0].nextElementSibling).is(selector)) {\n        return $([this[0].nextElementSibling]);\n      }\n\n      return $([]);\n    }\n\n    if (this[0].nextElementSibling) return $([this[0].nextElementSibling]);\n    return $([]);\n  }\n\n  return $([]);\n}\n\nfunction nextAll(selector) {\n  const nextEls = [];\n  let el = this[0];\n  if (!el) return $([]);\n\n  while (el.nextElementSibling) {\n    const next = el.nextElementSibling; // eslint-disable-line\n\n    if (selector) {\n      if ($(next).is(selector)) nextEls.push(next);\n    } else nextEls.push(next);\n\n    el = next;\n  }\n\n  return $(nextEls);\n}\n\nfunction prev(selector) {\n  if (this.length > 0) {\n    const el = this[0];\n\n    if (selector) {\n      if (el.previousElementSibling && $(el.previousElementSibling).is(selector)) {\n        return $([el.previousElementSibling]);\n      }\n\n      return $([]);\n    }\n\n    if (el.previousElementSibling) return $([el.previousElementSibling]);\n    return $([]);\n  }\n\n  return $([]);\n}\n\nfunction prevAll(selector) {\n  const prevEls = [];\n  let el = this[0];\n  if (!el) return $([]);\n\n  while (el.previousElementSibling) {\n    const prev = el.previousElementSibling; // eslint-disable-line\n\n    if (selector) {\n      if ($(prev).is(selector)) prevEls.push(prev);\n    } else prevEls.push(prev);\n\n    el = prev;\n  }\n\n  return $(prevEls);\n}\n\nfunction siblings(selector) {\n  return this.nextAll(selector).add(this.prevAll(selector));\n}\n\nfunction parent(selector) {\n  const parents = []; // eslint-disable-line\n\n  for (let i = 0; i < this.length; i += 1) {\n    if (this[i].parentNode !== null) {\n      if (selector) {\n        if ($(this[i].parentNode).is(selector)) parents.push(this[i].parentNode);\n      } else {\n        parents.push(this[i].parentNode);\n      }\n    }\n  }\n\n  return $(parents);\n}\n\nfunction parents(selector) {\n  const parents = []; // eslint-disable-line\n\n  for (let i = 0; i < this.length; i += 1) {\n    let parent = this[i].parentNode; // eslint-disable-line\n\n    while (parent) {\n      if (selector) {\n        if ($(parent).is(selector)) parents.push(parent);\n      } else {\n        parents.push(parent);\n      }\n\n      parent = parent.parentNode;\n    }\n  }\n\n  return $(parents);\n}\n\nfunction closest(selector) {\n  let closest = this; // eslint-disable-line\n\n  if (typeof selector === 'undefined') {\n    return $([]);\n  }\n\n  if (!closest.is(selector)) {\n    closest = closest.parents(selector).eq(0);\n  }\n\n  return closest;\n}\n\nfunction find(selector) {\n  const foundElements = [];\n\n  for (let i = 0; i < this.length; i += 1) {\n    const found = this[i].querySelectorAll(selector);\n\n    for (let j = 0; j < found.length; j += 1) {\n      foundElements.push(found[j]);\n    }\n  }\n\n  return $(foundElements);\n}\n\nfunction children(selector) {\n  const children = []; // eslint-disable-line\n\n  for (let i = 0; i < this.length; i += 1) {\n    const childNodes = this[i].children;\n\n    for (let j = 0; j < childNodes.length; j += 1) {\n      if (!selector || $(childNodes[j]).is(selector)) {\n        children.push(childNodes[j]);\n      }\n    }\n  }\n\n  return $(children);\n}\n\nfunction remove() {\n  for (let i = 0; i < this.length; i += 1) {\n    if (this[i].parentNode) this[i].parentNode.removeChild(this[i]);\n  }\n\n  return this;\n}\n\nfunction detach() {\n  return this.remove();\n}\n\nfunction add(...els) {\n  const dom = this;\n  let i;\n  let j;\n\n  for (i = 0; i < els.length; i += 1) {\n    const toAdd = $(els[i]);\n\n    for (j = 0; j < toAdd.length; j += 1) {\n      dom.push(toAdd[j]);\n    }\n  }\n\n  return dom;\n}\n\nfunction empty() {\n  for (let i = 0; i < this.length; i += 1) {\n    const el = this[i];\n\n    if (el.nodeType === 1) {\n      for (let j = 0; j < el.childNodes.length; j += 1) {\n        if (el.childNodes[j].parentNode) {\n          el.childNodes[j].parentNode.removeChild(el.childNodes[j]);\n        }\n      }\n\n      el.textContent = '';\n    }\n  }\n\n  return this;\n}\n\n// eslint-disable-next-line\n\nfunction scrollTo(...args) {\n  const window = getWindow();\n  let [left, top, duration, easing, callback] = args;\n\n  if (args.length === 4 && typeof easing === 'function') {\n    callback = easing;\n    [left, top, duration, callback, easing] = args;\n  }\n\n  if (typeof easing === 'undefined') easing = 'swing';\n  return this.each(function animate() {\n    const el = this;\n    let currentTop;\n    let currentLeft;\n    let maxTop;\n    let maxLeft;\n    let newTop;\n    let newLeft;\n    let scrollTop; // eslint-disable-line\n\n    let scrollLeft; // eslint-disable-line\n\n    let animateTop = top > 0 || top === 0;\n    let animateLeft = left > 0 || left === 0;\n\n    if (typeof easing === 'undefined') {\n      easing = 'swing';\n    }\n\n    if (animateTop) {\n      currentTop = el.scrollTop;\n\n      if (!duration) {\n        el.scrollTop = top;\n      }\n    }\n\n    if (animateLeft) {\n      currentLeft = el.scrollLeft;\n\n      if (!duration) {\n        el.scrollLeft = left;\n      }\n    }\n\n    if (!duration) return;\n\n    if (animateTop) {\n      maxTop = el.scrollHeight - el.offsetHeight;\n      newTop = Math.max(Math.min(top, maxTop), 0);\n    }\n\n    if (animateLeft) {\n      maxLeft = el.scrollWidth - el.offsetWidth;\n      newLeft = Math.max(Math.min(left, maxLeft), 0);\n    }\n\n    let startTime = null;\n    if (animateTop && newTop === currentTop) animateTop = false;\n    if (animateLeft && newLeft === currentLeft) animateLeft = false;\n\n    function render(time = new Date().getTime()) {\n      if (startTime === null) {\n        startTime = time;\n      }\n\n      const progress = Math.max(Math.min((time - startTime) / duration, 1), 0);\n      const easeProgress = easing === 'linear' ? progress : 0.5 - Math.cos(progress * Math.PI) / 2;\n      let done;\n      if (animateTop) scrollTop = currentTop + easeProgress * (newTop - currentTop);\n      if (animateLeft) scrollLeft = currentLeft + easeProgress * (newLeft - currentLeft);\n\n      if (animateTop && newTop > currentTop && scrollTop >= newTop) {\n        el.scrollTop = newTop;\n        done = true;\n      }\n\n      if (animateTop && newTop < currentTop && scrollTop <= newTop) {\n        el.scrollTop = newTop;\n        done = true;\n      }\n\n      if (animateLeft && newLeft > currentLeft && scrollLeft >= newLeft) {\n        el.scrollLeft = newLeft;\n        done = true;\n      }\n\n      if (animateLeft && newLeft < currentLeft && scrollLeft <= newLeft) {\n        el.scrollLeft = newLeft;\n        done = true;\n      }\n\n      if (done) {\n        if (callback) callback();\n        return;\n      }\n\n      if (animateTop) el.scrollTop = scrollTop;\n      if (animateLeft) el.scrollLeft = scrollLeft;\n      window.requestAnimationFrame(render);\n    }\n\n    window.requestAnimationFrame(render);\n  });\n} // scrollTop(top, duration, easing, callback) {\n\n\nfunction scrollTop(...args) {\n  let [top, duration, easing, callback] = args;\n\n  if (args.length === 3 && typeof easing === 'function') {\n    [top, duration, callback, easing] = args;\n  }\n\n  const dom = this;\n\n  if (typeof top === 'undefined') {\n    if (dom.length > 0) return dom[0].scrollTop;\n    return null;\n  }\n\n  return dom.scrollTo(undefined, top, duration, easing, callback);\n}\n\nfunction scrollLeft(...args) {\n  let [left, duration, easing, callback] = args;\n\n  if (args.length === 3 && typeof easing === 'function') {\n    [left, duration, callback, easing] = args;\n  }\n\n  const dom = this;\n\n  if (typeof left === 'undefined') {\n    if (dom.length > 0) return dom[0].scrollLeft;\n    return null;\n  }\n\n  return dom.scrollTo(left, undefined, duration, easing, callback);\n}\n\n// eslint-disable-next-line\n\nfunction animate(initialProps, initialParams) {\n  const window = getWindow();\n  const els = this;\n  const a = {\n    props: Object.assign({}, initialProps),\n    params: Object.assign({\n      duration: 300,\n      easing: 'swing' // or 'linear'\n\n      /* Callbacks\n      begin(elements)\n      complete(elements)\n      progress(elements, complete, remaining, start, tweenValue)\n      */\n\n    }, initialParams),\n    elements: els,\n    animating: false,\n    que: [],\n\n    easingProgress(easing, progress) {\n      if (easing === 'swing') {\n        return 0.5 - Math.cos(progress * Math.PI) / 2;\n      }\n\n      if (typeof easing === 'function') {\n        return easing(progress);\n      }\n\n      return progress;\n    },\n\n    stop() {\n      if (a.frameId) {\n        window.cancelAnimationFrame(a.frameId);\n      }\n\n      a.animating = false;\n      a.elements.each(el => {\n        const element = el;\n        delete element.dom7AnimateInstance;\n      });\n      a.que = [];\n    },\n\n    done(complete) {\n      a.animating = false;\n      a.elements.each(el => {\n        const element = el;\n        delete element.dom7AnimateInstance;\n      });\n      if (complete) complete(els);\n\n      if (a.que.length > 0) {\n        const que = a.que.shift();\n        a.animate(que[0], que[1]);\n      }\n    },\n\n    animate(props, params) {\n      if (a.animating) {\n        a.que.push([props, params]);\n        return a;\n      }\n\n      const elements = []; // Define & Cache Initials & Units\n\n      a.elements.each((el, index) => {\n        let initialFullValue;\n        let initialValue;\n        let unit;\n        let finalValue;\n        let finalFullValue;\n        if (!el.dom7AnimateInstance) a.elements[index].dom7AnimateInstance = a;\n        elements[index] = {\n          container: el\n        };\n        Object.keys(props).forEach(prop => {\n          initialFullValue = window.getComputedStyle(el, null).getPropertyValue(prop).replace(',', '.');\n          initialValue = parseFloat(initialFullValue);\n          unit = initialFullValue.replace(initialValue, '');\n          finalValue = parseFloat(props[prop]);\n          finalFullValue = props[prop] + unit;\n          elements[index][prop] = {\n            initialFullValue,\n            initialValue,\n            unit,\n            finalValue,\n            finalFullValue,\n            currentValue: initialValue\n          };\n        });\n      });\n      let startTime = null;\n      let time;\n      let elementsDone = 0;\n      let propsDone = 0;\n      let done;\n      let began = false;\n      a.animating = true;\n\n      function render() {\n        time = new Date().getTime();\n        let progress;\n        let easeProgress; // let el;\n\n        if (!began) {\n          began = true;\n          if (params.begin) params.begin(els);\n        }\n\n        if (startTime === null) {\n          startTime = time;\n        }\n\n        if (params.progress) {\n          // eslint-disable-next-line\n          params.progress(els, Math.max(Math.min((time - startTime) / params.duration, 1), 0), startTime + params.duration - time < 0 ? 0 : startTime + params.duration - time, startTime);\n        }\n\n        elements.forEach(element => {\n          const el = element;\n          if (done || el.done) return;\n          Object.keys(props).forEach(prop => {\n            if (done || el.done) return;\n            progress = Math.max(Math.min((time - startTime) / params.duration, 1), 0);\n            easeProgress = a.easingProgress(params.easing, progress);\n            const {\n              initialValue,\n              finalValue,\n              unit\n            } = el[prop];\n            el[prop].currentValue = initialValue + easeProgress * (finalValue - initialValue);\n            const currentValue = el[prop].currentValue;\n\n            if (finalValue > initialValue && currentValue >= finalValue || finalValue < initialValue && currentValue <= finalValue) {\n              el.container.style[prop] = finalValue + unit;\n              propsDone += 1;\n\n              if (propsDone === Object.keys(props).length) {\n                el.done = true;\n                elementsDone += 1;\n              }\n\n              if (elementsDone === elements.length) {\n                done = true;\n              }\n            }\n\n            if (done) {\n              a.done(params.complete);\n              return;\n            }\n\n            el.container.style[prop] = currentValue + unit;\n          });\n        });\n        if (done) return; // Then call\n\n        a.frameId = window.requestAnimationFrame(render);\n      }\n\n      a.frameId = window.requestAnimationFrame(render);\n      return a;\n    }\n\n  };\n\n  if (a.elements.length === 0) {\n    return els;\n  }\n\n  let animateInstance;\n\n  for (let i = 0; i < a.elements.length; i += 1) {\n    if (a.elements[i].dom7AnimateInstance) {\n      animateInstance = a.elements[i].dom7AnimateInstance;\n    } else a.elements[i].dom7AnimateInstance = a;\n  }\n\n  if (!animateInstance) {\n    animateInstance = a;\n  }\n\n  if (initialProps === 'stop') {\n    animateInstance.stop();\n  } else {\n    animateInstance.animate(a.props, a.params);\n  }\n\n  return els;\n}\n\nfunction stop() {\n  const els = this;\n\n  for (let i = 0; i < els.length; i += 1) {\n    if (els[i].dom7AnimateInstance) {\n      els[i].dom7AnimateInstance.stop();\n    }\n  }\n}\n\nconst noTrigger = 'resize scroll'.split(' ');\n\nfunction shortcut(name) {\n  function eventHandler(...args) {\n    if (typeof args[0] === 'undefined') {\n      for (let i = 0; i < this.length; i += 1) {\n        if (noTrigger.indexOf(name) < 0) {\n          if (name in this[i]) this[i][name]();else {\n            $(this[i]).trigger(name);\n          }\n        }\n      }\n\n      return this;\n    }\n\n    return this.on(name, ...args);\n  }\n\n  return eventHandler;\n}\n\nconst click = shortcut('click');\nconst blur = shortcut('blur');\nconst focus = shortcut('focus');\nconst focusin = shortcut('focusin');\nconst focusout = shortcut('focusout');\nconst keyup = shortcut('keyup');\nconst keydown = shortcut('keydown');\nconst keypress = shortcut('keypress');\nconst submit = shortcut('submit');\nconst change = shortcut('change');\nconst mousedown = shortcut('mousedown');\nconst mousemove = shortcut('mousemove');\nconst mouseup = shortcut('mouseup');\nconst mouseenter = shortcut('mouseenter');\nconst mouseleave = shortcut('mouseleave');\nconst mouseout = shortcut('mouseout');\nconst mouseover = shortcut('mouseover');\nconst touchstart = shortcut('touchstart');\nconst touchend = shortcut('touchend');\nconst touchmove = shortcut('touchmove');\nconst resize = shortcut('resize');\nconst scroll = shortcut('scroll');\n\nexport default $;\nexport { $, add, addClass, animate, animationEnd, append, appendTo, attr, blur, change, children, click, closest, css, data, dataset, detach, each, empty, eq, filter, find, focus, focusin, focusout, hasClass, height, hide, html, index, insertAfter, insertBefore, is, keydown, keypress, keyup, mousedown, mouseenter, mouseleave, mousemove, mouseout, mouseover, mouseup, next, nextAll, off, offset, on, once, outerHeight, outerWidth, parent, parents, prepend, prependTo, prev, prevAll, prop, remove, removeAttr, removeClass, removeData, resize, scroll, scrollLeft, scrollTo, scrollTop, show, siblings, stop, styles, submit, text, toggleClass, touchend, touchmove, touchstart, transform, transition, transitionEnd, trigger, val, value, width };\n", "import { $, addClass, removeClass, hasClass, toggleClass, attr, removeAttr, transform, transition, on, off, trigger, transitionEnd, outerWidth, outerHeight, styles, offset, css, each, html, text, is, index, eq, append, prepend, next, nextAll, prev, prevAll, parent, parents, closest, find, children, filter, remove } from 'dom7';\nconst Methods = {\n  addClass,\n  removeClass,\n  hasClass,\n  toggleClass,\n  attr,\n  removeAttr,\n  transform,\n  transition,\n  on,\n  off,\n  trigger,\n  transitionEnd,\n  outerWidth,\n  outerHeight,\n  styles,\n  offset,\n  css,\n  each,\n  html,\n  text,\n  is,\n  index,\n  eq,\n  append,\n  prepend,\n  next,\n  nextAll,\n  prev,\n  prevAll,\n  parent,\n  parents,\n  closest,\n  find,\n  children,\n  filter,\n  remove\n};\nObject.keys(Methods).forEach(methodName => {\n  Object.defineProperty($.fn, methodName, {\n    value: Methods[methodName],\n    writable: true\n  });\n});\nexport default $;", "import { getWindow } from 'ssr-window';\n\nfunction deleteProps(obj) {\n  const object = obj;\n  Object.keys(object).forEach(key => {\n    try {\n      object[key] = null;\n    } catch (e) {// no getter for object\n    }\n\n    try {\n      delete object[key];\n    } catch (e) {// something got wrong\n    }\n  });\n}\n\nfunction nextTick(callback, delay) {\n  if (delay === void 0) {\n    delay = 0;\n  }\n\n  return setTimeout(callback, delay);\n}\n\nfunction now() {\n  return Date.now();\n}\n\nfunction getComputedStyle(el) {\n  const window = getWindow();\n  let style;\n\n  if (window.getComputedStyle) {\n    style = window.getComputedStyle(el, null);\n  }\n\n  if (!style && el.currentStyle) {\n    style = el.currentStyle;\n  }\n\n  if (!style) {\n    style = el.style;\n  }\n\n  return style;\n}\n\nfunction getTranslate(el, axis) {\n  if (axis === void 0) {\n    axis = 'x';\n  }\n\n  const window = getWindow();\n  let matrix;\n  let curTransform;\n  let transformMatrix;\n  const curStyle = getComputedStyle(el, null);\n\n  if (window.WebKitCSSMatrix) {\n    curTransform = curStyle.transform || curStyle.webkitTransform;\n\n    if (curTransform.split(',').length > 6) {\n      curTransform = curTransform.split(', ').map(a => a.replace(',', '.')).join(', ');\n    } // Some old versions of Webkit choke when 'none' is passed; pass\n    // empty string instead in this case\n\n\n    transformMatrix = new window.WebKitCSSMatrix(curTransform === 'none' ? '' : curTransform);\n  } else {\n    transformMatrix = curStyle.MozTransform || curStyle.OTransform || curStyle.MsTransform || curStyle.msTransform || curStyle.transform || curStyle.getPropertyValue('transform').replace('translate(', 'matrix(1, 0, 0, 1,');\n    matrix = transformMatrix.toString().split(',');\n  }\n\n  if (axis === 'x') {\n    // Latest Chrome and webkits Fix\n    if (window.WebKitCSSMatrix) curTransform = transformMatrix.m41; // Crazy IE10 Matrix\n    else if (matrix.length === 16) curTransform = parseFloat(matrix[12]); // Normal Browsers\n    else curTransform = parseFloat(matrix[4]);\n  }\n\n  if (axis === 'y') {\n    // Latest Chrome and webkits Fix\n    if (window.WebKitCSSMatrix) curTransform = transformMatrix.m42; // Crazy IE10 Matrix\n    else if (matrix.length === 16) curTransform = parseFloat(matrix[13]); // Normal Browsers\n    else curTransform = parseFloat(matrix[5]);\n  }\n\n  return curTransform || 0;\n}\n\nfunction isObject(o) {\n  return typeof o === 'object' && o !== null && o.constructor && Object.prototype.toString.call(o).slice(8, -1) === 'Object';\n}\n\nfunction isNode(node) {\n  // eslint-disable-next-line\n  if (typeof window !== 'undefined' && typeof window.HTMLElement !== 'undefined') {\n    return node instanceof HTMLElement;\n  }\n\n  return node && (node.nodeType === 1 || node.nodeType === 11);\n}\n\nfunction extend() {\n  const to = Object(arguments.length <= 0 ? undefined : arguments[0]);\n  const noExtend = ['__proto__', 'constructor', 'prototype'];\n\n  for (let i = 1; i < arguments.length; i += 1) {\n    const nextSource = i < 0 || arguments.length <= i ? undefined : arguments[i];\n\n    if (nextSource !== undefined && nextSource !== null && !isNode(nextSource)) {\n      const keysArray = Object.keys(Object(nextSource)).filter(key => noExtend.indexOf(key) < 0);\n\n      for (let nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex += 1) {\n        const nextKey = keysArray[nextIndex];\n        const desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);\n\n        if (desc !== undefined && desc.enumerable) {\n          if (isObject(to[nextKey]) && isObject(nextSource[nextKey])) {\n            if (nextSource[nextKey].__swiper__) {\n              to[nextKey] = nextSource[nextKey];\n            } else {\n              extend(to[nextKey], nextSource[nextKey]);\n            }\n          } else if (!isObject(to[nextKey]) && isObject(nextSource[nextKey])) {\n            to[nextKey] = {};\n\n            if (nextSource[nextKey].__swiper__) {\n              to[nextKey] = nextSource[nextKey];\n            } else {\n              extend(to[nextKey], nextSource[nextKey]);\n            }\n          } else {\n            to[nextKey] = nextSource[nextKey];\n          }\n        }\n      }\n    }\n  }\n\n  return to;\n}\n\nfunction setCSSProperty(el, varName, varValue) {\n  el.style.setProperty(varName, varValue);\n}\n\nfunction animateCSSModeScroll(_ref) {\n  let {\n    swiper,\n    targetPosition,\n    side\n  } = _ref;\n  const window = getWindow();\n  const startPosition = -swiper.translate;\n  let startTime = null;\n  let time;\n  const duration = swiper.params.speed;\n  swiper.wrapperEl.style.scrollSnapType = 'none';\n  window.cancelAnimationFrame(swiper.cssModeFrameID);\n  const dir = targetPosition > startPosition ? 'next' : 'prev';\n\n  const isOutOfBound = (current, target) => {\n    return dir === 'next' && current >= target || dir === 'prev' && current <= target;\n  };\n\n  const animate = () => {\n    time = new Date().getTime();\n\n    if (startTime === null) {\n      startTime = time;\n    }\n\n    const progress = Math.max(Math.min((time - startTime) / duration, 1), 0);\n    const easeProgress = 0.5 - Math.cos(progress * Math.PI) / 2;\n    let currentPosition = startPosition + easeProgress * (targetPosition - startPosition);\n\n    if (isOutOfBound(currentPosition, targetPosition)) {\n      currentPosition = targetPosition;\n    }\n\n    swiper.wrapperEl.scrollTo({\n      [side]: currentPosition\n    });\n\n    if (isOutOfBound(currentPosition, targetPosition)) {\n      swiper.wrapperEl.style.overflow = 'hidden';\n      swiper.wrapperEl.style.scrollSnapType = '';\n      setTimeout(() => {\n        swiper.wrapperEl.style.overflow = '';\n        swiper.wrapperEl.scrollTo({\n          [side]: currentPosition\n        });\n      });\n      window.cancelAnimationFrame(swiper.cssModeFrameID);\n      return;\n    }\n\n    swiper.cssModeFrameID = window.requestAnimationFrame(animate);\n  };\n\n  animate();\n}\n\nexport { animateCSSModeScroll, deleteProps, nextTick, now, getTranslate, isObject, extend, getComputedStyle, setCSSProperty };", "import { getWindow, getDocument } from 'ssr-window';\nlet support;\n\nfunction calcSupport() {\n  const window = getWindow();\n  const document = getDocument();\n  return {\n    smoothScroll: document.documentElement && 'scrollBehavior' in document.documentElement.style,\n    touch: !!('ontouchstart' in window || window.DocumentTouch && document instanceof window.DocumentTouch),\n    passiveListener: function checkPassiveListener() {\n      let supportsPassive = false;\n\n      try {\n        const opts = Object.defineProperty({}, 'passive', {\n          // eslint-disable-next-line\n          get() {\n            supportsPassive = true;\n          }\n\n        });\n        window.addEventListener('testPassiveListener', null, opts);\n      } catch (e) {// No support\n      }\n\n      return supportsPassive;\n    }(),\n    gestures: function checkGestures() {\n      return 'ongesturestart' in window;\n    }()\n  };\n}\n\nfunction getSupport() {\n  if (!support) {\n    support = calcSupport();\n  }\n\n  return support;\n}\n\nexport { getSupport };", "import { getWindow } from 'ssr-window';\nimport { getSupport } from './get-support.js';\nlet deviceCached;\n\nfunction calcDevice(_temp) {\n  let {\n    userAgent\n  } = _temp === void 0 ? {} : _temp;\n  const support = getSupport();\n  const window = getWindow();\n  const platform = window.navigator.platform;\n  const ua = userAgent || window.navigator.userAgent;\n  const device = {\n    ios: false,\n    android: false\n  };\n  const screenWidth = window.screen.width;\n  const screenHeight = window.screen.height;\n  const android = ua.match(/(Android);?[\\s\\/]+([\\d.]+)?/); // eslint-disable-line\n\n  let ipad = ua.match(/(iPad).*OS\\s([\\d_]+)/);\n  const ipod = ua.match(/(iPod)(.*OS\\s([\\d_]+))?/);\n  const iphone = !ipad && ua.match(/(iPhone\\sOS|iOS)\\s([\\d_]+)/);\n  const windows = platform === 'Win32';\n  let macos = platform === 'MacIntel'; // iPadOs 13 fix\n\n  const iPadScreens = ['1024x1366', '1366x1024', '834x1194', '1194x834', '834x1112', '1112x834', '768x1024', '1024x768', '820x1180', '1180x820', '810x1080', '1080x810'];\n\n  if (!ipad && macos && support.touch && iPadScreens.indexOf(`${screenWidth}x${screenHeight}`) >= 0) {\n    ipad = ua.match(/(Version)\\/([\\d.]+)/);\n    if (!ipad) ipad = [0, 1, '13_0_0'];\n    macos = false;\n  } // Android\n\n\n  if (android && !windows) {\n    device.os = 'android';\n    device.android = true;\n  }\n\n  if (ipad || iphone || ipod) {\n    device.os = 'ios';\n    device.ios = true;\n  } // Export object\n\n\n  return device;\n}\n\nfunction getDevice(overrides) {\n  if (overrides === void 0) {\n    overrides = {};\n  }\n\n  if (!deviceCached) {\n    deviceCached = calcDevice(overrides);\n  }\n\n  return deviceCached;\n}\n\nexport { getDevice };", "import { getWindow } from 'ssr-window';\nlet browser;\n\nfunction calcBrowser() {\n  const window = getWindow();\n\n  function isSafari() {\n    const ua = window.navigator.userAgent.toLowerCase();\n    return ua.indexOf('safari') >= 0 && ua.indexOf('chrome') < 0 && ua.indexOf('android') < 0;\n  }\n\n  return {\n    isSafari: isSafari(),\n    isWebView: /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(window.navigator.userAgent)\n  };\n}\n\nfunction getBrowser() {\n  if (!browser) {\n    browser = calcBrowser();\n  }\n\n  return browser;\n}\n\nexport { getBrowser };", "import { getWindow } from 'ssr-window';\nexport default function Resize(_ref) {\n  let {\n    swiper,\n    on,\n    emit\n  } = _ref;\n  const window = getWindow();\n  let observer = null;\n  let animationFrame = null;\n\n  const resizeHandler = () => {\n    if (!swiper || swiper.destroyed || !swiper.initialized) return;\n    emit('beforeResize');\n    emit('resize');\n  };\n\n  const createObserver = () => {\n    if (!swiper || swiper.destroyed || !swiper.initialized) return;\n    observer = new ResizeObserver(entries => {\n      animationFrame = window.requestAnimationFrame(() => {\n        const {\n          width,\n          height\n        } = swiper;\n        let newWidth = width;\n        let newHeight = height;\n        entries.forEach(_ref2 => {\n          let {\n            contentBoxSize,\n            contentRect,\n            target\n          } = _ref2;\n          if (target && target !== swiper.el) return;\n          newWidth = contentRect ? contentRect.width : (contentBoxSize[0] || contentBoxSize).inlineSize;\n          newHeight = contentRect ? contentRect.height : (contentBoxSize[0] || contentBoxSize).blockSize;\n        });\n\n        if (newWidth !== width || newHeight !== height) {\n          resizeHandler();\n        }\n      });\n    });\n    observer.observe(swiper.el);\n  };\n\n  const removeObserver = () => {\n    if (animationFrame) {\n      window.cancelAnimationFrame(animationFrame);\n    }\n\n    if (observer && observer.unobserve && swiper.el) {\n      observer.unobserve(swiper.el);\n      observer = null;\n    }\n  };\n\n  const orientationChangeHandler = () => {\n    if (!swiper || swiper.destroyed || !swiper.initialized) return;\n    emit('orientationchange');\n  };\n\n  on('init', () => {\n    if (swiper.params.resizeObserver && typeof window.ResizeObserver !== 'undefined') {\n      createObserver();\n      return;\n    }\n\n    window.addEventListener('resize', resizeHandler);\n    window.addEventListener('orientationchange', orientationChangeHandler);\n  });\n  on('destroy', () => {\n    removeObserver();\n    window.removeEventListener('resize', resizeHandler);\n    window.removeEventListener('orientationchange', orientationChangeHandler);\n  });\n}", "import { getWindow } from 'ssr-window';\nexport default function Observer(_ref) {\n  let {\n    swiper,\n    extendParams,\n    on,\n    emit\n  } = _ref;\n  const observers = [];\n  const window = getWindow();\n\n  const attach = function (target, options) {\n    if (options === void 0) {\n      options = {};\n    }\n\n    const ObserverFunc = window.MutationObserver || window.WebkitMutationObserver;\n    const observer = new ObserverFunc(mutations => {\n      // The observerUpdate event should only be triggered\n      // once despite the number of mutations.  Additional\n      // triggers are redundant and are very costly\n      if (mutations.length === 1) {\n        emit('observerUpdate', mutations[0]);\n        return;\n      }\n\n      const observerUpdate = function observerUpdate() {\n        emit('observerUpdate', mutations[0]);\n      };\n\n      if (window.requestAnimationFrame) {\n        window.requestAnimationFrame(observerUpdate);\n      } else {\n        window.setTimeout(observerUpdate, 0);\n      }\n    });\n    observer.observe(target, {\n      attributes: typeof options.attributes === 'undefined' ? true : options.attributes,\n      childList: typeof options.childList === 'undefined' ? true : options.childList,\n      characterData: typeof options.characterData === 'undefined' ? true : options.characterData\n    });\n    observers.push(observer);\n  };\n\n  const init = () => {\n    if (!swiper.params.observer) return;\n\n    if (swiper.params.observeParents) {\n      const containerParents = swiper.$el.parents();\n\n      for (let i = 0; i < containerParents.length; i += 1) {\n        attach(containerParents[i]);\n      }\n    } // Observe container\n\n\n    attach(swiper.$el[0], {\n      childList: swiper.params.observeSlideChildren\n    }); // Observe wrapper\n\n    attach(swiper.$wrapperEl[0], {\n      attributes: false\n    });\n  };\n\n  const destroy = () => {\n    observers.forEach(observer => {\n      observer.disconnect();\n    });\n    observers.splice(0, observers.length);\n  };\n\n  extendParams({\n    observer: false,\n    observeParents: false,\n    observeSlideChildren: false\n  });\n  on('init', init);\n  on('destroy', destroy);\n}", "/* eslint-disable no-underscore-dangle */\nexport default {\n  on(events, handler, priority) {\n    const self = this;\n    if (!self.eventsListeners || self.destroyed) return self;\n    if (typeof handler !== 'function') return self;\n    const method = priority ? 'unshift' : 'push';\n    events.split(' ').forEach(event => {\n      if (!self.eventsListeners[event]) self.eventsListeners[event] = [];\n      self.eventsListeners[event][method](handler);\n    });\n    return self;\n  },\n\n  once(events, handler, priority) {\n    const self = this;\n    if (!self.eventsListeners || self.destroyed) return self;\n    if (typeof handler !== 'function') return self;\n\n    function onceHandler() {\n      self.off(events, onceHandler);\n\n      if (onceHandler.__emitterProxy) {\n        delete onceHandler.__emitterProxy;\n      }\n\n      for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n        args[_key] = arguments[_key];\n      }\n\n      handler.apply(self, args);\n    }\n\n    onceHandler.__emitterProxy = handler;\n    return self.on(events, onceHandler, priority);\n  },\n\n  onAny(handler, priority) {\n    const self = this;\n    if (!self.eventsListeners || self.destroyed) return self;\n    if (typeof handler !== 'function') return self;\n    const method = priority ? 'unshift' : 'push';\n\n    if (self.eventsAnyListeners.indexOf(handler) < 0) {\n      self.eventsAnyListeners[method](handler);\n    }\n\n    return self;\n  },\n\n  offAny(handler) {\n    const self = this;\n    if (!self.eventsListeners || self.destroyed) return self;\n    if (!self.eventsAnyListeners) return self;\n    const index = self.eventsAnyListeners.indexOf(handler);\n\n    if (index >= 0) {\n      self.eventsAnyListeners.splice(index, 1);\n    }\n\n    return self;\n  },\n\n  off(events, handler) {\n    const self = this;\n    if (!self.eventsListeners || self.destroyed) return self;\n    if (!self.eventsListeners) return self;\n    events.split(' ').forEach(event => {\n      if (typeof handler === 'undefined') {\n        self.eventsListeners[event] = [];\n      } else if (self.eventsListeners[event]) {\n        self.eventsListeners[event].forEach((eventHandler, index) => {\n          if (eventHandler === handler || eventHandler.__emitterProxy && eventHandler.__emitterProxy === handler) {\n            self.eventsListeners[event].splice(index, 1);\n          }\n        });\n      }\n    });\n    return self;\n  },\n\n  emit() {\n    const self = this;\n    if (!self.eventsListeners || self.destroyed) return self;\n    if (!self.eventsListeners) return self;\n    let events;\n    let data;\n    let context;\n\n    for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n      args[_key2] = arguments[_key2];\n    }\n\n    if (typeof args[0] === 'string' || Array.isArray(args[0])) {\n      events = args[0];\n      data = args.slice(1, args.length);\n      context = self;\n    } else {\n      events = args[0].events;\n      data = args[0].data;\n      context = args[0].context || self;\n    }\n\n    data.unshift(context);\n    const eventsArray = Array.isArray(events) ? events : events.split(' ');\n    eventsArray.forEach(event => {\n      if (self.eventsAnyListeners && self.eventsAnyListeners.length) {\n        self.eventsAnyListeners.forEach(eventHandler => {\n          eventHandler.apply(context, [event, ...data]);\n        });\n      }\n\n      if (self.eventsListeners && self.eventsListeners[event]) {\n        self.eventsListeners[event].forEach(eventHandler => {\n          eventHandler.apply(context, data);\n        });\n      }\n    });\n    return self;\n  }\n\n};", "export default function updateSize() {\n  const swiper = this;\n  let width;\n  let height;\n  const $el = swiper.$el;\n\n  if (typeof swiper.params.width !== 'undefined' && swiper.params.width !== null) {\n    width = swiper.params.width;\n  } else {\n    width = $el[0].clientWidth;\n  }\n\n  if (typeof swiper.params.height !== 'undefined' && swiper.params.height !== null) {\n    height = swiper.params.height;\n  } else {\n    height = $el[0].clientHeight;\n  }\n\n  if (width === 0 && swiper.isHorizontal() || height === 0 && swiper.isVertical()) {\n    return;\n  } // Subtract paddings\n\n\n  width = width - parseInt($el.css('padding-left') || 0, 10) - parseInt($el.css('padding-right') || 0, 10);\n  height = height - parseInt($el.css('padding-top') || 0, 10) - parseInt($el.css('padding-bottom') || 0, 10);\n  if (Number.isNaN(width)) width = 0;\n  if (Number.isNaN(height)) height = 0;\n  Object.assign(swiper, {\n    width,\n    height,\n    size: swiper.isHorizontal() ? width : height\n  });\n}", "import { setCSSProperty } from '../../shared/utils.js';\nexport default function updateSlides() {\n  const swiper = this;\n\n  function getDirectionLabel(property) {\n    if (swiper.isHorizontal()) {\n      return property;\n    } // prettier-ignore\n\n\n    return {\n      'width': 'height',\n      'margin-top': 'margin-left',\n      'margin-bottom ': 'margin-right',\n      'margin-left': 'margin-top',\n      'margin-right': 'margin-bottom',\n      'padding-left': 'padding-top',\n      'padding-right': 'padding-bottom',\n      'marginRight': 'marginBottom'\n    }[property];\n  }\n\n  function getDirectionPropertyValue(node, label) {\n    return parseFloat(node.getPropertyValue(getDirectionLabel(label)) || 0);\n  }\n\n  const params = swiper.params;\n  const {\n    $wrapperEl,\n    size: swiperSize,\n    rtlTranslate: rtl,\n    wrongRTL\n  } = swiper;\n  const isVirtual = swiper.virtual && params.virtual.enabled;\n  const previousSlidesLength = isVirtual ? swiper.virtual.slides.length : swiper.slides.length;\n  const slides = $wrapperEl.children(`.${swiper.params.slideClass}`);\n  const slidesLength = isVirtual ? swiper.virtual.slides.length : slides.length;\n  let snapGrid = [];\n  const slidesGrid = [];\n  const slidesSizesGrid = [];\n  let offsetBefore = params.slidesOffsetBefore;\n\n  if (typeof offsetBefore === 'function') {\n    offsetBefore = params.slidesOffsetBefore.call(swiper);\n  }\n\n  let offsetAfter = params.slidesOffsetAfter;\n\n  if (typeof offsetAfter === 'function') {\n    offsetAfter = params.slidesOffsetAfter.call(swiper);\n  }\n\n  const previousSnapGridLength = swiper.snapGrid.length;\n  const previousSlidesGridLength = swiper.slidesGrid.length;\n  let spaceBetween = params.spaceBetween;\n  let slidePosition = -offsetBefore;\n  let prevSlideSize = 0;\n  let index = 0;\n\n  if (typeof swiperSize === 'undefined') {\n    return;\n  }\n\n  if (typeof spaceBetween === 'string' && spaceBetween.indexOf('%') >= 0) {\n    spaceBetween = parseFloat(spaceBetween.replace('%', '')) / 100 * swiperSize;\n  }\n\n  swiper.virtualSize = -spaceBetween; // reset margins\n\n  if (rtl) slides.css({\n    marginLeft: '',\n    marginBottom: '',\n    marginTop: ''\n  });else slides.css({\n    marginRight: '',\n    marginBottom: '',\n    marginTop: ''\n  }); // reset cssMode offsets\n\n  if (params.centeredSlides && params.cssMode) {\n    setCSSProperty(swiper.wrapperEl, '--swiper-centered-offset-before', '');\n    setCSSProperty(swiper.wrapperEl, '--swiper-centered-offset-after', '');\n  }\n\n  const gridEnabled = params.grid && params.grid.rows > 1 && swiper.grid;\n\n  if (gridEnabled) {\n    swiper.grid.initSlides(slidesLength);\n  } // Calc slides\n\n\n  let slideSize;\n  const shouldResetSlideSize = params.slidesPerView === 'auto' && params.breakpoints && Object.keys(params.breakpoints).filter(key => {\n    return typeof params.breakpoints[key].slidesPerView !== 'undefined';\n  }).length > 0;\n\n  for (let i = 0; i < slidesLength; i += 1) {\n    slideSize = 0;\n    const slide = slides.eq(i);\n\n    if (gridEnabled) {\n      swiper.grid.updateSlide(i, slide, slidesLength, getDirectionLabel);\n    }\n\n    if (slide.css('display') === 'none') continue; // eslint-disable-line\n\n    if (params.slidesPerView === 'auto') {\n      if (shouldResetSlideSize) {\n        slides[i].style[getDirectionLabel('width')] = ``;\n      }\n\n      const slideStyles = getComputedStyle(slide[0]);\n      const currentTransform = slide[0].style.transform;\n      const currentWebKitTransform = slide[0].style.webkitTransform;\n\n      if (currentTransform) {\n        slide[0].style.transform = 'none';\n      }\n\n      if (currentWebKitTransform) {\n        slide[0].style.webkitTransform = 'none';\n      }\n\n      if (params.roundLengths) {\n        slideSize = swiper.isHorizontal() ? slide.outerWidth(true) : slide.outerHeight(true);\n      } else {\n        // eslint-disable-next-line\n        const width = getDirectionPropertyValue(slideStyles, 'width');\n        const paddingLeft = getDirectionPropertyValue(slideStyles, 'padding-left');\n        const paddingRight = getDirectionPropertyValue(slideStyles, 'padding-right');\n        const marginLeft = getDirectionPropertyValue(slideStyles, 'margin-left');\n        const marginRight = getDirectionPropertyValue(slideStyles, 'margin-right');\n        const boxSizing = slideStyles.getPropertyValue('box-sizing');\n\n        if (boxSizing && boxSizing === 'border-box') {\n          slideSize = width + marginLeft + marginRight;\n        } else {\n          const {\n            clientWidth,\n            offsetWidth\n          } = slide[0];\n          slideSize = width + paddingLeft + paddingRight + marginLeft + marginRight + (offsetWidth - clientWidth);\n        }\n      }\n\n      if (currentTransform) {\n        slide[0].style.transform = currentTransform;\n      }\n\n      if (currentWebKitTransform) {\n        slide[0].style.webkitTransform = currentWebKitTransform;\n      }\n\n      if (params.roundLengths) slideSize = Math.floor(slideSize);\n    } else {\n      slideSize = (swiperSize - (params.slidesPerView - 1) * spaceBetween) / params.slidesPerView;\n      if (params.roundLengths) slideSize = Math.floor(slideSize);\n\n      if (slides[i]) {\n        slides[i].style[getDirectionLabel('width')] = `${slideSize}px`;\n      }\n    }\n\n    if (slides[i]) {\n      slides[i].swiperSlideSize = slideSize;\n    }\n\n    slidesSizesGrid.push(slideSize);\n\n    if (params.centeredSlides) {\n      slidePosition = slidePosition + slideSize / 2 + prevSlideSize / 2 + spaceBetween;\n      if (prevSlideSize === 0 && i !== 0) slidePosition = slidePosition - swiperSize / 2 - spaceBetween;\n      if (i === 0) slidePosition = slidePosition - swiperSize / 2 - spaceBetween;\n      if (Math.abs(slidePosition) < 1 / 1000) slidePosition = 0;\n      if (params.roundLengths) slidePosition = Math.floor(slidePosition);\n      if (index % params.slidesPerGroup === 0) snapGrid.push(slidePosition);\n      slidesGrid.push(slidePosition);\n    } else {\n      if (params.roundLengths) slidePosition = Math.floor(slidePosition);\n      if ((index - Math.min(swiper.params.slidesPerGroupSkip, index)) % swiper.params.slidesPerGroup === 0) snapGrid.push(slidePosition);\n      slidesGrid.push(slidePosition);\n      slidePosition = slidePosition + slideSize + spaceBetween;\n    }\n\n    swiper.virtualSize += slideSize + spaceBetween;\n    prevSlideSize = slideSize;\n    index += 1;\n  }\n\n  swiper.virtualSize = Math.max(swiper.virtualSize, swiperSize) + offsetAfter;\n\n  if (rtl && wrongRTL && (params.effect === 'slide' || params.effect === 'coverflow')) {\n    $wrapperEl.css({\n      width: `${swiper.virtualSize + params.spaceBetween}px`\n    });\n  }\n\n  if (params.setWrapperSize) {\n    $wrapperEl.css({\n      [getDirectionLabel('width')]: `${swiper.virtualSize + params.spaceBetween}px`\n    });\n  }\n\n  if (gridEnabled) {\n    swiper.grid.updateWrapperSize(slideSize, snapGrid, getDirectionLabel);\n  } // Remove last grid elements depending on width\n\n\n  if (!params.centeredSlides) {\n    const newSlidesGrid = [];\n\n    for (let i = 0; i < snapGrid.length; i += 1) {\n      let slidesGridItem = snapGrid[i];\n      if (params.roundLengths) slidesGridItem = Math.floor(slidesGridItem);\n\n      if (snapGrid[i] <= swiper.virtualSize - swiperSize) {\n        newSlidesGrid.push(slidesGridItem);\n      }\n    }\n\n    snapGrid = newSlidesGrid;\n\n    if (Math.floor(swiper.virtualSize - swiperSize) - Math.floor(snapGrid[snapGrid.length - 1]) > 1) {\n      snapGrid.push(swiper.virtualSize - swiperSize);\n    }\n  }\n\n  if (snapGrid.length === 0) snapGrid = [0];\n\n  if (params.spaceBetween !== 0) {\n    const key = swiper.isHorizontal() && rtl ? 'marginLeft' : getDirectionLabel('marginRight');\n    slides.filter((_, slideIndex) => {\n      if (!params.cssMode) return true;\n\n      if (slideIndex === slides.length - 1) {\n        return false;\n      }\n\n      return true;\n    }).css({\n      [key]: `${spaceBetween}px`\n    });\n  }\n\n  if (params.centeredSlides && params.centeredSlidesBounds) {\n    let allSlidesSize = 0;\n    slidesSizesGrid.forEach(slideSizeValue => {\n      allSlidesSize += slideSizeValue + (params.spaceBetween ? params.spaceBetween : 0);\n    });\n    allSlidesSize -= params.spaceBetween;\n    const maxSnap = allSlidesSize - swiperSize;\n    snapGrid = snapGrid.map(snap => {\n      if (snap < 0) return -offsetBefore;\n      if (snap > maxSnap) return maxSnap + offsetAfter;\n      return snap;\n    });\n  }\n\n  if (params.centerInsufficientSlides) {\n    let allSlidesSize = 0;\n    slidesSizesGrid.forEach(slideSizeValue => {\n      allSlidesSize += slideSizeValue + (params.spaceBetween ? params.spaceBetween : 0);\n    });\n    allSlidesSize -= params.spaceBetween;\n\n    if (allSlidesSize < swiperSize) {\n      const allSlidesOffset = (swiperSize - allSlidesSize) / 2;\n      snapGrid.forEach((snap, snapIndex) => {\n        snapGrid[snapIndex] = snap - allSlidesOffset;\n      });\n      slidesGrid.forEach((snap, snapIndex) => {\n        slidesGrid[snapIndex] = snap + allSlidesOffset;\n      });\n    }\n  }\n\n  Object.assign(swiper, {\n    slides,\n    snapGrid,\n    slidesGrid,\n    slidesSizesGrid\n  });\n\n  if (params.centeredSlides && params.cssMode && !params.centeredSlidesBounds) {\n    setCSSProperty(swiper.wrapperEl, '--swiper-centered-offset-before', `${-snapGrid[0]}px`);\n    setCSSProperty(swiper.wrapperEl, '--swiper-centered-offset-after', `${swiper.size / 2 - slidesSizesGrid[slidesSizesGrid.length - 1] / 2}px`);\n    const addToSnapGrid = -swiper.snapGrid[0];\n    const addToSlidesGrid = -swiper.slidesGrid[0];\n    swiper.snapGrid = swiper.snapGrid.map(v => v + addToSnapGrid);\n    swiper.slidesGrid = swiper.slidesGrid.map(v => v + addToSlidesGrid);\n  }\n\n  if (slidesLength !== previousSlidesLength) {\n    swiper.emit('slidesLengthChange');\n  }\n\n  if (snapGrid.length !== previousSnapGridLength) {\n    if (swiper.params.watchOverflow) swiper.checkOverflow();\n    swiper.emit('snapGridLengthChange');\n  }\n\n  if (slidesGrid.length !== previousSlidesGridLength) {\n    swiper.emit('slidesGridLengthChange');\n  }\n\n  if (params.watchSlidesProgress) {\n    swiper.updateSlidesOffset();\n  }\n\n  if (!isVirtual && !params.cssMode && (params.effect === 'slide' || params.effect === 'fade')) {\n    const backFaceHiddenClass = `${params.containerModifierClass}backface-hidden`;\n    const hasClassBackfaceClassAdded = swiper.$el.hasClass(backFaceHiddenClass);\n\n    if (slidesLength <= params.maxBackfaceHiddenSlides) {\n      if (!hasClassBackfaceClassAdded) swiper.$el.addClass(backFaceHiddenClass);\n    } else if (hasClassBackfaceClassAdded) {\n      swiper.$el.removeClass(backFaceHiddenClass);\n    }\n  }\n}", "import $ from '../../shared/dom.js';\nexport default function updateAutoHeight(speed) {\n  const swiper = this;\n  const activeSlides = [];\n  const isVirtual = swiper.virtual && swiper.params.virtual.enabled;\n  let newHeight = 0;\n  let i;\n\n  if (typeof speed === 'number') {\n    swiper.setTransition(speed);\n  } else if (speed === true) {\n    swiper.setTransition(swiper.params.speed);\n  }\n\n  const getSlideByIndex = index => {\n    if (isVirtual) {\n      return swiper.slides.filter(el => parseInt(el.getAttribute('data-swiper-slide-index'), 10) === index)[0];\n    }\n\n    return swiper.slides.eq(index)[0];\n  }; // Find slides currently in view\n\n\n  if (swiper.params.slidesPerView !== 'auto' && swiper.params.slidesPerView > 1) {\n    if (swiper.params.centeredSlides) {\n      (swiper.visibleSlides || $([])).each(slide => {\n        activeSlides.push(slide);\n      });\n    } else {\n      for (i = 0; i < Math.ceil(swiper.params.slidesPerView); i += 1) {\n        const index = swiper.activeIndex + i;\n        if (index > swiper.slides.length && !isVirtual) break;\n        activeSlides.push(getSlideByIndex(index));\n      }\n    }\n  } else {\n    activeSlides.push(getSlideByIndex(swiper.activeIndex));\n  } // Find new height from highest slide in view\n\n\n  for (i = 0; i < activeSlides.length; i += 1) {\n    if (typeof activeSlides[i] !== 'undefined') {\n      const height = activeSlides[i].offsetHeight;\n      newHeight = height > newHeight ? height : newHeight;\n    }\n  } // Update Height\n\n\n  if (newHeight || newHeight === 0) swiper.$wrapperEl.css('height', `${newHeight}px`);\n}", "export default function updateSlidesOffset() {\n  const swiper = this;\n  const slides = swiper.slides;\n\n  for (let i = 0; i < slides.length; i += 1) {\n    slides[i].swiperSlideOffset = swiper.isHorizontal() ? slides[i].offsetLeft : slides[i].offsetTop;\n  }\n}", "import $ from '../../shared/dom.js';\nexport default function updateSlidesProgress(translate) {\n  if (translate === void 0) {\n    translate = this && this.translate || 0;\n  }\n\n  const swiper = this;\n  const params = swiper.params;\n  const {\n    slides,\n    rtlTranslate: rtl,\n    snapGrid\n  } = swiper;\n  if (slides.length === 0) return;\n  if (typeof slides[0].swiperSlideOffset === 'undefined') swiper.updateSlidesOffset();\n  let offsetCenter = -translate;\n  if (rtl) offsetCenter = translate; // Visible Slides\n\n  slides.removeClass(params.slideVisibleClass);\n  swiper.visibleSlidesIndexes = [];\n  swiper.visibleSlides = [];\n\n  for (let i = 0; i < slides.length; i += 1) {\n    const slide = slides[i];\n    let slideOffset = slide.swiperSlideOffset;\n\n    if (params.cssMode && params.centeredSlides) {\n      slideOffset -= slides[0].swiperSlideOffset;\n    }\n\n    const slideProgress = (offsetCenter + (params.centeredSlides ? swiper.minTranslate() : 0) - slideOffset) / (slide.swiperSlideSize + params.spaceBetween);\n    const originalSlideProgress = (offsetCenter - snapGrid[0] + (params.centeredSlides ? swiper.minTranslate() : 0) - slideOffset) / (slide.swiperSlideSize + params.spaceBetween);\n    const slideBefore = -(offsetCenter - slideOffset);\n    const slideAfter = slideBefore + swiper.slidesSizesGrid[i];\n    const isVisible = slideBefore >= 0 && slideBefore < swiper.size - 1 || slideAfter > 1 && slideAfter <= swiper.size || slideBefore <= 0 && slideAfter >= swiper.size;\n\n    if (isVisible) {\n      swiper.visibleSlides.push(slide);\n      swiper.visibleSlidesIndexes.push(i);\n      slides.eq(i).addClass(params.slideVisibleClass);\n    }\n\n    slide.progress = rtl ? -slideProgress : slideProgress;\n    slide.originalProgress = rtl ? -originalSlideProgress : originalSlideProgress;\n  }\n\n  swiper.visibleSlides = $(swiper.visibleSlides);\n}", "export default function updateProgress(translate) {\n  const swiper = this;\n\n  if (typeof translate === 'undefined') {\n    const multiplier = swiper.rtlTranslate ? -1 : 1; // eslint-disable-next-line\n\n    translate = swiper && swiper.translate && swiper.translate * multiplier || 0;\n  }\n\n  const params = swiper.params;\n  const translatesDiff = swiper.maxTranslate() - swiper.minTranslate();\n  let {\n    progress,\n    isBeginning,\n    isEnd\n  } = swiper;\n  const wasBeginning = isBeginning;\n  const wasEnd = isEnd;\n\n  if (translatesDiff === 0) {\n    progress = 0;\n    isBeginning = true;\n    isEnd = true;\n  } else {\n    progress = (translate - swiper.minTranslate()) / translatesDiff;\n    isBeginning = progress <= 0;\n    isEnd = progress >= 1;\n  }\n\n  Object.assign(swiper, {\n    progress,\n    isBeginning,\n    isEnd\n  });\n  if (params.watchSlidesProgress || params.centeredSlides && params.autoHeight) swiper.updateSlidesProgress(translate);\n\n  if (isBeginning && !wasBeginning) {\n    swiper.emit('reachBeginning toEdge');\n  }\n\n  if (isEnd && !wasEnd) {\n    swiper.emit('reachEnd toEdge');\n  }\n\n  if (wasBeginning && !isBeginning || wasEnd && !isEnd) {\n    swiper.emit('fromEdge');\n  }\n\n  swiper.emit('progress', progress);\n}", "export default function updateSlidesClasses() {\n  const swiper = this;\n  const {\n    slides,\n    params,\n    $wrapperEl,\n    activeIndex,\n    realIndex\n  } = swiper;\n  const isVirtual = swiper.virtual && params.virtual.enabled;\n  slides.removeClass(`${params.slideActiveClass} ${params.slideNextClass} ${params.slidePrevClass} ${params.slideDuplicateActiveClass} ${params.slideDuplicateNextClass} ${params.slideDuplicatePrevClass}`);\n  let activeSlide;\n\n  if (isVirtual) {\n    activeSlide = swiper.$wrapperEl.find(`.${params.slideClass}[data-swiper-slide-index=\"${activeIndex}\"]`);\n  } else {\n    activeSlide = slides.eq(activeIndex);\n  } // Active classes\n\n\n  activeSlide.addClass(params.slideActiveClass);\n\n  if (params.loop) {\n    // Duplicate to all looped slides\n    if (activeSlide.hasClass(params.slideDuplicateClass)) {\n      $wrapperEl.children(`.${params.slideClass}:not(.${params.slideDuplicateClass})[data-swiper-slide-index=\"${realIndex}\"]`).addClass(params.slideDuplicateActiveClass);\n    } else {\n      $wrapperEl.children(`.${params.slideClass}.${params.slideDuplicateClass}[data-swiper-slide-index=\"${realIndex}\"]`).addClass(params.slideDuplicateActiveClass);\n    }\n  } // Next Slide\n\n\n  let nextSlide = activeSlide.nextAll(`.${params.slideClass}`).eq(0).addClass(params.slideNextClass);\n\n  if (params.loop && nextSlide.length === 0) {\n    nextSlide = slides.eq(0);\n    nextSlide.addClass(params.slideNextClass);\n  } // Prev Slide\n\n\n  let prevSlide = activeSlide.prevAll(`.${params.slideClass}`).eq(0).addClass(params.slidePrevClass);\n\n  if (params.loop && prevSlide.length === 0) {\n    prevSlide = slides.eq(-1);\n    prevSlide.addClass(params.slidePrevClass);\n  }\n\n  if (params.loop) {\n    // Duplicate to all looped slides\n    if (nextSlide.hasClass(params.slideDuplicateClass)) {\n      $wrapperEl.children(`.${params.slideClass}:not(.${params.slideDuplicateClass})[data-swiper-slide-index=\"${nextSlide.attr('data-swiper-slide-index')}\"]`).addClass(params.slideDuplicateNextClass);\n    } else {\n      $wrapperEl.children(`.${params.slideClass}.${params.slideDuplicateClass}[data-swiper-slide-index=\"${nextSlide.attr('data-swiper-slide-index')}\"]`).addClass(params.slideDuplicateNextClass);\n    }\n\n    if (prevSlide.hasClass(params.slideDuplicateClass)) {\n      $wrapperEl.children(`.${params.slideClass}:not(.${params.slideDuplicateClass})[data-swiper-slide-index=\"${prevSlide.attr('data-swiper-slide-index')}\"]`).addClass(params.slideDuplicatePrevClass);\n    } else {\n      $wrapperEl.children(`.${params.slideClass}.${params.slideDuplicateClass}[data-swiper-slide-index=\"${prevSlide.attr('data-swiper-slide-index')}\"]`).addClass(params.slideDuplicatePrevClass);\n    }\n  }\n\n  swiper.emitSlidesClasses();\n}", "export default function updateActiveIndex(newActiveIndex) {\n  const swiper = this;\n  const translate = swiper.rtlTranslate ? swiper.translate : -swiper.translate;\n  const {\n    slidesGrid,\n    snapGrid,\n    params,\n    activeIndex: previousIndex,\n    realIndex: previousRealIndex,\n    snapIndex: previousSnapIndex\n  } = swiper;\n  let activeIndex = newActiveIndex;\n  let snapIndex;\n\n  if (typeof activeIndex === 'undefined') {\n    for (let i = 0; i < slidesGrid.length; i += 1) {\n      if (typeof slidesGrid[i + 1] !== 'undefined') {\n        if (translate >= slidesGrid[i] && translate < slidesGrid[i + 1] - (slidesGrid[i + 1] - slidesGrid[i]) / 2) {\n          activeIndex = i;\n        } else if (translate >= slidesGrid[i] && translate < slidesGrid[i + 1]) {\n          activeIndex = i + 1;\n        }\n      } else if (translate >= slidesGrid[i]) {\n        activeIndex = i;\n      }\n    } // Normalize slideIndex\n\n\n    if (params.normalizeSlideIndex) {\n      if (activeIndex < 0 || typeof activeIndex === 'undefined') activeIndex = 0;\n    }\n  }\n\n  if (snapGrid.indexOf(translate) >= 0) {\n    snapIndex = snapGrid.indexOf(translate);\n  } else {\n    const skip = Math.min(params.slidesPerGroupSkip, activeIndex);\n    snapIndex = skip + Math.floor((activeIndex - skip) / params.slidesPerGroup);\n  }\n\n  if (snapIndex >= snapGrid.length) snapIndex = snapGrid.length - 1;\n\n  if (activeIndex === previousIndex) {\n    if (snapIndex !== previousSnapIndex) {\n      swiper.snapIndex = snapIndex;\n      swiper.emit('snapIndexChange');\n    }\n\n    return;\n  } // Get real index\n\n\n  const realIndex = parseInt(swiper.slides.eq(activeIndex).attr('data-swiper-slide-index') || activeIndex, 10);\n  Object.assign(swiper, {\n    snapIndex,\n    realIndex,\n    previousIndex,\n    activeIndex\n  });\n  swiper.emit('activeIndexChange');\n  swiper.emit('snapIndexChange');\n\n  if (previousRealIndex !== realIndex) {\n    swiper.emit('realIndexChange');\n  }\n\n  if (swiper.initialized || swiper.params.runCallbacksOnInit) {\n    swiper.emit('slideChange');\n  }\n}", "import $ from '../../shared/dom.js';\nexport default function updateClickedSlide(e) {\n  const swiper = this;\n  const params = swiper.params;\n  const slide = $(e).closest(`.${params.slideClass}`)[0];\n  let slideFound = false;\n  let slideIndex;\n\n  if (slide) {\n    for (let i = 0; i < swiper.slides.length; i += 1) {\n      if (swiper.slides[i] === slide) {\n        slideFound = true;\n        slideIndex = i;\n        break;\n      }\n    }\n  }\n\n  if (slide && slideFound) {\n    swiper.clickedSlide = slide;\n\n    if (swiper.virtual && swiper.params.virtual.enabled) {\n      swiper.clickedIndex = parseInt($(slide).attr('data-swiper-slide-index'), 10);\n    } else {\n      swiper.clickedIndex = slideIndex;\n    }\n  } else {\n    swiper.clickedSlide = undefined;\n    swiper.clickedIndex = undefined;\n    return;\n  }\n\n  if (params.slideToClickedSlide && swiper.clickedIndex !== undefined && swiper.clickedIndex !== swiper.activeIndex) {\n    swiper.slideToClickedSlide();\n  }\n}", "import updateSize from './updateSize.js';\nimport updateSlides from './updateSlides.js';\nimport updateAutoHeight from './updateAutoHeight.js';\nimport updateSlidesOffset from './updateSlidesOffset.js';\nimport updateSlidesProgress from './updateSlidesProgress.js';\nimport updateProgress from './updateProgress.js';\nimport updateSlidesClasses from './updateSlidesClasses.js';\nimport updateActiveIndex from './updateActiveIndex.js';\nimport updateClickedSlide from './updateClickedSlide.js';\nexport default {\n  updateSize,\n  updateSlides,\n  updateAutoHeight,\n  updateSlidesOffset,\n  updateSlidesProgress,\n  updateProgress,\n  updateSlidesClasses,\n  updateActiveIndex,\n  updateClickedSlide\n};", "import { getTranslate } from '../../shared/utils.js';\nexport default function getSwiperTranslate(axis) {\n  if (axis === void 0) {\n    axis = this.isHorizontal() ? 'x' : 'y';\n  }\n\n  const swiper = this;\n  const {\n    params,\n    rtlTranslate: rtl,\n    translate,\n    $wrapperEl\n  } = swiper;\n\n  if (params.virtualTranslate) {\n    return rtl ? -translate : translate;\n  }\n\n  if (params.cssMode) {\n    return translate;\n  }\n\n  let currentTranslate = getTranslate($wrapperEl[0], axis);\n  if (rtl) currentTranslate = -currentTranslate;\n  return currentTranslate || 0;\n}", "export default function setTranslate(translate, byController) {\n  const swiper = this;\n  const {\n    rtlTranslate: rtl,\n    params,\n    $wrapperEl,\n    wrapperEl,\n    progress\n  } = swiper;\n  let x = 0;\n  let y = 0;\n  const z = 0;\n\n  if (swiper.isHorizontal()) {\n    x = rtl ? -translate : translate;\n  } else {\n    y = translate;\n  }\n\n  if (params.roundLengths) {\n    x = Math.floor(x);\n    y = Math.floor(y);\n  }\n\n  if (params.cssMode) {\n    wrapperEl[swiper.isHorizontal() ? 'scrollLeft' : 'scrollTop'] = swiper.isHorizontal() ? -x : -y;\n  } else if (!params.virtualTranslate) {\n    $wrapperEl.transform(`translate3d(${x}px, ${y}px, ${z}px)`);\n  }\n\n  swiper.previousTranslate = swiper.translate;\n  swiper.translate = swiper.isHorizontal() ? x : y; // Check if we need to update progress\n\n  let newProgress;\n  const translatesDiff = swiper.maxTranslate() - swiper.minTranslate();\n\n  if (translatesDiff === 0) {\n    newProgress = 0;\n  } else {\n    newProgress = (translate - swiper.minTranslate()) / translatesDiff;\n  }\n\n  if (newProgress !== progress) {\n    swiper.updateProgress(translate);\n  }\n\n  swiper.emit('setTranslate', swiper.translate, byController);\n}", "export default function minTranslate() {\n  return -this.snapGrid[0];\n}", "export default function maxTranslate() {\n  return -this.snapGrid[this.snapGrid.length - 1];\n}", "import { animateCSSModeScroll } from '../../shared/utils.js';\nexport default function translateTo(translate, speed, runCallbacks, translateBounds, internal) {\n  if (translate === void 0) {\n    translate = 0;\n  }\n\n  if (speed === void 0) {\n    speed = this.params.speed;\n  }\n\n  if (runCallbacks === void 0) {\n    runCallbacks = true;\n  }\n\n  if (translateBounds === void 0) {\n    translateBounds = true;\n  }\n\n  const swiper = this;\n  const {\n    params,\n    wrapperEl\n  } = swiper;\n\n  if (swiper.animating && params.preventInteractionOnTransition) {\n    return false;\n  }\n\n  const minTranslate = swiper.minTranslate();\n  const maxTranslate = swiper.maxTranslate();\n  let newTranslate;\n  if (translateBounds && translate > minTranslate) newTranslate = minTranslate;else if (translateBounds && translate < maxTranslate) newTranslate = maxTranslate;else newTranslate = translate; // Update progress\n\n  swiper.updateProgress(newTranslate);\n\n  if (params.cssMode) {\n    const isH = swiper.isHorizontal();\n\n    if (speed === 0) {\n      wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = -newTranslate;\n    } else {\n      if (!swiper.support.smoothScroll) {\n        animateCSSModeScroll({\n          swiper,\n          targetPosition: -newTranslate,\n          side: isH ? 'left' : 'top'\n        });\n        return true;\n      }\n\n      wrapperEl.scrollTo({\n        [isH ? 'left' : 'top']: -newTranslate,\n        behavior: 'smooth'\n      });\n    }\n\n    return true;\n  }\n\n  if (speed === 0) {\n    swiper.setTransition(0);\n    swiper.setTranslate(newTranslate);\n\n    if (runCallbacks) {\n      swiper.emit('beforeTransitionStart', speed, internal);\n      swiper.emit('transitionEnd');\n    }\n  } else {\n    swiper.setTransition(speed);\n    swiper.setTranslate(newTranslate);\n\n    if (runCallbacks) {\n      swiper.emit('beforeTransitionStart', speed, internal);\n      swiper.emit('transitionStart');\n    }\n\n    if (!swiper.animating) {\n      swiper.animating = true;\n\n      if (!swiper.onTranslateToWrapperTransitionEnd) {\n        swiper.onTranslateToWrapperTransitionEnd = function transitionEnd(e) {\n          if (!swiper || swiper.destroyed) return;\n          if (e.target !== this) return;\n          swiper.$wrapperEl[0].removeEventListener('transitionend', swiper.onTranslateToWrapperTransitionEnd);\n          swiper.$wrapperEl[0].removeEventListener('webkitTransitionEnd', swiper.onTranslateToWrapperTransitionEnd);\n          swiper.onTranslateToWrapperTransitionEnd = null;\n          delete swiper.onTranslateToWrapperTransitionEnd;\n\n          if (runCallbacks) {\n            swiper.emit('transitionEnd');\n          }\n        };\n      }\n\n      swiper.$wrapperEl[0].addEventListener('transitionend', swiper.onTranslateToWrapperTransitionEnd);\n      swiper.$wrapperEl[0].addEventListener('webkitTransitionEnd', swiper.onTranslateToWrapperTransitionEnd);\n    }\n  }\n\n  return true;\n}", "import getTranslate from './getTranslate.js';\nimport setTranslate from './setTranslate.js';\nimport minTranslate from './minTranslate.js';\nimport maxTranslate from './maxTranslate.js';\nimport translateTo from './translateTo.js';\nexport default {\n  getTranslate,\n  setTranslate,\n  minTranslate,\n  maxTranslate,\n  translateTo\n};", "export default function setTransition(duration, byController) {\n  const swiper = this;\n\n  if (!swiper.params.cssMode) {\n    swiper.$wrapperEl.transition(duration);\n  }\n\n  swiper.emit('setTransition', duration, byController);\n}", "export default function transitionEmit(_ref) {\n  let {\n    swiper,\n    runCallbacks,\n    direction,\n    step\n  } = _ref;\n  const {\n    activeIndex,\n    previousIndex\n  } = swiper;\n  let dir = direction;\n\n  if (!dir) {\n    if (activeIndex > previousIndex) dir = 'next';else if (activeIndex < previousIndex) dir = 'prev';else dir = 'reset';\n  }\n\n  swiper.emit(`transition${step}`);\n\n  if (runCallbacks && activeIndex !== previousIndex) {\n    if (dir === 'reset') {\n      swiper.emit(`slideResetTransition${step}`);\n      return;\n    }\n\n    swiper.emit(`slideChangeTransition${step}`);\n\n    if (dir === 'next') {\n      swiper.emit(`slideNextTransition${step}`);\n    } else {\n      swiper.emit(`slidePrevTransition${step}`);\n    }\n  }\n}", "import transitionEmit from './transitionEmit.js';\nexport default function transitionStart(runCallbacks, direction) {\n  if (runCallbacks === void 0) {\n    runCallbacks = true;\n  }\n\n  const swiper = this;\n  const {\n    params\n  } = swiper;\n  if (params.cssMode) return;\n\n  if (params.autoHeight) {\n    swiper.updateAutoHeight();\n  }\n\n  transitionEmit({\n    swiper,\n    runCallbacks,\n    direction,\n    step: 'Start'\n  });\n}", "import transitionEmit from './transitionEmit.js';\nexport default function transitionEnd(runCallbacks, direction) {\n  if (runCallbacks === void 0) {\n    runCallbacks = true;\n  }\n\n  const swiper = this;\n  const {\n    params\n  } = swiper;\n  swiper.animating = false;\n  if (params.cssMode) return;\n  swiper.setTransition(0);\n  transitionEmit({\n    swiper,\n    runCallbacks,\n    direction,\n    step: 'End'\n  });\n}", "import setTransition from './setTransition.js';\nimport transitionStart from './transitionStart.js';\nimport transitionEnd from './transitionEnd.js';\nexport default {\n  setTransition,\n  transitionStart,\n  transitionEnd\n};", "import { animateCSSModeScroll } from '../../shared/utils.js';\nexport default function slideTo(index, speed, runCallbacks, internal, initial) {\n  if (index === void 0) {\n    index = 0;\n  }\n\n  if (speed === void 0) {\n    speed = this.params.speed;\n  }\n\n  if (runCallbacks === void 0) {\n    runCallbacks = true;\n  }\n\n  if (typeof index !== 'number' && typeof index !== 'string') {\n    throw new Error(`The 'index' argument cannot have type other than 'number' or 'string'. [${typeof index}] given.`);\n  }\n\n  if (typeof index === 'string') {\n    /**\n     * The `index` argument converted from `string` to `number`.\n     * @type {number}\n     */\n    const indexAsNumber = parseInt(index, 10);\n    /**\n     * Determines whether the `index` argument is a valid `number`\n     * after being converted from the `string` type.\n     * @type {boolean}\n     */\n\n    const isValidNumber = isFinite(indexAsNumber);\n\n    if (!isValidNumber) {\n      throw new Error(`The passed-in 'index' (string) couldn't be converted to 'number'. [${index}] given.`);\n    } // Knowing that the converted `index` is a valid number,\n    // we can update the original argument's value.\n\n\n    index = indexAsNumber;\n  }\n\n  const swiper = this;\n  let slideIndex = index;\n  if (slideIndex < 0) slideIndex = 0;\n  const {\n    params,\n    snapGrid,\n    slidesGrid,\n    previousIndex,\n    activeIndex,\n    rtlTranslate: rtl,\n    wrapperEl,\n    enabled\n  } = swiper;\n\n  if (swiper.animating && params.preventInteractionOnTransition || !enabled && !internal && !initial) {\n    return false;\n  }\n\n  const skip = Math.min(swiper.params.slidesPerGroupSkip, slideIndex);\n  let snapIndex = skip + Math.floor((slideIndex - skip) / swiper.params.slidesPerGroup);\n  if (snapIndex >= snapGrid.length) snapIndex = snapGrid.length - 1;\n\n  if ((activeIndex || params.initialSlide || 0) === (previousIndex || 0) && runCallbacks) {\n    swiper.emit('beforeSlideChangeStart');\n  }\n\n  const translate = -snapGrid[snapIndex]; // Update progress\n\n  swiper.updateProgress(translate); // Normalize slideIndex\n\n  if (params.normalizeSlideIndex) {\n    for (let i = 0; i < slidesGrid.length; i += 1) {\n      const normalizedTranslate = -Math.floor(translate * 100);\n      const normalizedGrid = Math.floor(slidesGrid[i] * 100);\n      const normalizedGridNext = Math.floor(slidesGrid[i + 1] * 100);\n\n      if (typeof slidesGrid[i + 1] !== 'undefined') {\n        if (normalizedTranslate >= normalizedGrid && normalizedTranslate < normalizedGridNext - (normalizedGridNext - normalizedGrid) / 2) {\n          slideIndex = i;\n        } else if (normalizedTranslate >= normalizedGrid && normalizedTranslate < normalizedGridNext) {\n          slideIndex = i + 1;\n        }\n      } else if (normalizedTranslate >= normalizedGrid) {\n        slideIndex = i;\n      }\n    }\n  } // Directions locks\n\n\n  if (swiper.initialized && slideIndex !== activeIndex) {\n    if (!swiper.allowSlideNext && translate < swiper.translate && translate < swiper.minTranslate()) {\n      return false;\n    }\n\n    if (!swiper.allowSlidePrev && translate > swiper.translate && translate > swiper.maxTranslate()) {\n      if ((activeIndex || 0) !== slideIndex) return false;\n    }\n  }\n\n  let direction;\n  if (slideIndex > activeIndex) direction = 'next';else if (slideIndex < activeIndex) direction = 'prev';else direction = 'reset'; // Update Index\n\n  if (rtl && -translate === swiper.translate || !rtl && translate === swiper.translate) {\n    swiper.updateActiveIndex(slideIndex); // Update Height\n\n    if (params.autoHeight) {\n      swiper.updateAutoHeight();\n    }\n\n    swiper.updateSlidesClasses();\n\n    if (params.effect !== 'slide') {\n      swiper.setTranslate(translate);\n    }\n\n    if (direction !== 'reset') {\n      swiper.transitionStart(runCallbacks, direction);\n      swiper.transitionEnd(runCallbacks, direction);\n    }\n\n    return false;\n  }\n\n  if (params.cssMode) {\n    const isH = swiper.isHorizontal();\n    const t = rtl ? translate : -translate;\n\n    if (speed === 0) {\n      const isVirtual = swiper.virtual && swiper.params.virtual.enabled;\n\n      if (isVirtual) {\n        swiper.wrapperEl.style.scrollSnapType = 'none';\n        swiper._immediateVirtual = true;\n      }\n\n      wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = t;\n\n      if (isVirtual) {\n        requestAnimationFrame(() => {\n          swiper.wrapperEl.style.scrollSnapType = '';\n          swiper._swiperImmediateVirtual = false;\n        });\n      }\n    } else {\n      if (!swiper.support.smoothScroll) {\n        animateCSSModeScroll({\n          swiper,\n          targetPosition: t,\n          side: isH ? 'left' : 'top'\n        });\n        return true;\n      }\n\n      wrapperEl.scrollTo({\n        [isH ? 'left' : 'top']: t,\n        behavior: 'smooth'\n      });\n    }\n\n    return true;\n  }\n\n  swiper.setTransition(speed);\n  swiper.setTranslate(translate);\n  swiper.updateActiveIndex(slideIndex);\n  swiper.updateSlidesClasses();\n  swiper.emit('beforeTransitionStart', speed, internal);\n  swiper.transitionStart(runCallbacks, direction);\n\n  if (speed === 0) {\n    swiper.transitionEnd(runCallbacks, direction);\n  } else if (!swiper.animating) {\n    swiper.animating = true;\n\n    if (!swiper.onSlideToWrapperTransitionEnd) {\n      swiper.onSlideToWrapperTransitionEnd = function transitionEnd(e) {\n        if (!swiper || swiper.destroyed) return;\n        if (e.target !== this) return;\n        swiper.$wrapperEl[0].removeEventListener('transitionend', swiper.onSlideToWrapperTransitionEnd);\n        swiper.$wrapperEl[0].removeEventListener('webkitTransitionEnd', swiper.onSlideToWrapperTransitionEnd);\n        swiper.onSlideToWrapperTransitionEnd = null;\n        delete swiper.onSlideToWrapperTransitionEnd;\n        swiper.transitionEnd(runCallbacks, direction);\n      };\n    }\n\n    swiper.$wrapperEl[0].addEventListener('transitionend', swiper.onSlideToWrapperTransitionEnd);\n    swiper.$wrapperEl[0].addEventListener('webkitTransitionEnd', swiper.onSlideToWrapperTransitionEnd);\n  }\n\n  return true;\n}", "export default function slideToLoop(index, speed, runCallbacks, internal) {\n  if (index === void 0) {\n    index = 0;\n  }\n\n  if (speed === void 0) {\n    speed = this.params.speed;\n  }\n\n  if (runCallbacks === void 0) {\n    runCallbacks = true;\n  }\n\n  if (typeof index === 'string') {\n    /**\n     * The `index` argument converted from `string` to `number`.\n     * @type {number}\n     */\n    const indexAsNumber = parseInt(index, 10);\n    /**\n     * Determines whether the `index` argument is a valid `number`\n     * after being converted from the `string` type.\n     * @type {boolean}\n     */\n\n    const isValidNumber = isFinite(indexAsNumber);\n\n    if (!isValidNumber) {\n      throw new Error(`The passed-in 'index' (string) couldn't be converted to 'number'. [${index}] given.`);\n    } // Knowing that the converted `index` is a valid number,\n    // we can update the original argument's value.\n\n\n    index = indexAsNumber;\n  }\n\n  const swiper = this;\n  let newIndex = index;\n\n  if (swiper.params.loop) {\n    newIndex += swiper.loopedSlides;\n  }\n\n  return swiper.slideTo(newIndex, speed, runCallbacks, internal);\n}", "/* eslint no-unused-vars: \"off\" */\nexport default function slideNext(speed, runCallbacks, internal) {\n  if (speed === void 0) {\n    speed = this.params.speed;\n  }\n\n  if (runCallbacks === void 0) {\n    runCallbacks = true;\n  }\n\n  const swiper = this;\n  const {\n    animating,\n    enabled,\n    params\n  } = swiper;\n  if (!enabled) return swiper;\n  let perGroup = params.slidesPerGroup;\n\n  if (params.slidesPerView === 'auto' && params.slidesPerGroup === 1 && params.slidesPerGroupAuto) {\n    perGroup = Math.max(swiper.slidesPerViewDynamic('current', true), 1);\n  }\n\n  const increment = swiper.activeIndex < params.slidesPerGroupSkip ? 1 : perGroup;\n\n  if (params.loop) {\n    if (animating && params.loopPreventsSlide) return false;\n    swiper.loopFix(); // eslint-disable-next-line\n\n    swiper._clientLeft = swiper.$wrapperEl[0].clientLeft;\n  }\n\n  if (params.rewind && swiper.isEnd) {\n    return swiper.slideTo(0, speed, runCallbacks, internal);\n  }\n\n  return swiper.slideTo(swiper.activeIndex + increment, speed, runCallbacks, internal);\n}", "/* eslint no-unused-vars: \"off\" */\nexport default function slidePrev(speed, runCallbacks, internal) {\n  if (speed === void 0) {\n    speed = this.params.speed;\n  }\n\n  if (runCallbacks === void 0) {\n    runCallbacks = true;\n  }\n\n  const swiper = this;\n  const {\n    params,\n    animating,\n    snapGrid,\n    slidesGrid,\n    rtlTranslate,\n    enabled\n  } = swiper;\n  if (!enabled) return swiper;\n\n  if (params.loop) {\n    if (animating && params.loopPreventsSlide) return false;\n    swiper.loopFix(); // eslint-disable-next-line\n\n    swiper._clientLeft = swiper.$wrapperEl[0].clientLeft;\n  }\n\n  const translate = rtlTranslate ? swiper.translate : -swiper.translate;\n\n  function normalize(val) {\n    if (val < 0) return -Math.floor(Math.abs(val));\n    return Math.floor(val);\n  }\n\n  const normalizedTranslate = normalize(translate);\n  const normalizedSnapGrid = snapGrid.map(val => normalize(val));\n  let prevSnap = snapGrid[normalizedSnapGrid.indexOf(normalizedTranslate) - 1];\n\n  if (typeof prevSnap === 'undefined' && params.cssMode) {\n    let prevSnapIndex;\n    snapGrid.forEach((snap, snapIndex) => {\n      if (normalizedTranslate >= snap) {\n        // prevSnap = snap;\n        prevSnapIndex = snapIndex;\n      }\n    });\n\n    if (typeof prevSnapIndex !== 'undefined') {\n      prevSnap = snapGrid[prevSnapIndex > 0 ? prevSnapIndex - 1 : prevSnapIndex];\n    }\n  }\n\n  let prevIndex = 0;\n\n  if (typeof prevSnap !== 'undefined') {\n    prevIndex = slidesGrid.indexOf(prevSnap);\n    if (prevIndex < 0) prevIndex = swiper.activeIndex - 1;\n\n    if (params.slidesPerView === 'auto' && params.slidesPerGroup === 1 && params.slidesPerGroupAuto) {\n      prevIndex = prevIndex - swiper.slidesPerViewDynamic('previous', true) + 1;\n      prevIndex = Math.max(prevIndex, 0);\n    }\n  }\n\n  if (params.rewind && swiper.isBeginning) {\n    const lastIndex = swiper.params.virtual && swiper.params.virtual.enabled && swiper.virtual ? swiper.virtual.slides.length - 1 : swiper.slides.length - 1;\n    return swiper.slideTo(lastIndex, speed, runCallbacks, internal);\n  }\n\n  return swiper.slideTo(prevIndex, speed, runCallbacks, internal);\n}", "/* eslint no-unused-vars: \"off\" */\nexport default function slideReset(speed, runCallbacks, internal) {\n  if (speed === void 0) {\n    speed = this.params.speed;\n  }\n\n  if (runCallbacks === void 0) {\n    runCallbacks = true;\n  }\n\n  const swiper = this;\n  return swiper.slideTo(swiper.activeIndex, speed, runCallbacks, internal);\n}", "/* eslint no-unused-vars: \"off\" */\nexport default function slideToClosest(speed, runCallbacks, internal, threshold) {\n  if (speed === void 0) {\n    speed = this.params.speed;\n  }\n\n  if (runCallbacks === void 0) {\n    runCallbacks = true;\n  }\n\n  if (threshold === void 0) {\n    threshold = 0.5;\n  }\n\n  const swiper = this;\n  let index = swiper.activeIndex;\n  const skip = Math.min(swiper.params.slidesPerGroupSkip, index);\n  const snapIndex = skip + Math.floor((index - skip) / swiper.params.slidesPerGroup);\n  const translate = swiper.rtlTranslate ? swiper.translate : -swiper.translate;\n\n  if (translate >= swiper.snapGrid[snapIndex]) {\n    // The current translate is on or after the current snap index, so the choice\n    // is between the current index and the one after it.\n    const currentSnap = swiper.snapGrid[snapIndex];\n    const nextSnap = swiper.snapGrid[snapIndex + 1];\n\n    if (translate - currentSnap > (nextSnap - currentSnap) * threshold) {\n      index += swiper.params.slidesPerGroup;\n    }\n  } else {\n    // The current translate is before the current snap index, so the choice\n    // is between the current index and the one before it.\n    const prevSnap = swiper.snapGrid[snapIndex - 1];\n    const currentSnap = swiper.snapGrid[snapIndex];\n\n    if (translate - prevSnap <= (currentSnap - prevSnap) * threshold) {\n      index -= swiper.params.slidesPerGroup;\n    }\n  }\n\n  index = Math.max(index, 0);\n  index = Math.min(index, swiper.slidesGrid.length - 1);\n  return swiper.slideTo(index, speed, runCallbacks, internal);\n}", "import $ from '../../shared/dom.js';\nimport { nextTick } from '../../shared/utils.js';\nexport default function slideToClickedSlide() {\n  const swiper = this;\n  const {\n    params,\n    $wrapperEl\n  } = swiper;\n  const slidesPerView = params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : params.slidesPerView;\n  let slideToIndex = swiper.clickedIndex;\n  let realIndex;\n\n  if (params.loop) {\n    if (swiper.animating) return;\n    realIndex = parseInt($(swiper.clickedSlide).attr('data-swiper-slide-index'), 10);\n\n    if (params.centeredSlides) {\n      if (slideToIndex < swiper.loopedSlides - slidesPerView / 2 || slideToIndex > swiper.slides.length - swiper.loopedSlides + slidesPerView / 2) {\n        swiper.loopFix();\n        slideToIndex = $wrapperEl.children(`.${params.slideClass}[data-swiper-slide-index=\"${realIndex}\"]:not(.${params.slideDuplicateClass})`).eq(0).index();\n        nextTick(() => {\n          swiper.slideTo(slideToIndex);\n        });\n      } else {\n        swiper.slideTo(slideToIndex);\n      }\n    } else if (slideToIndex > swiper.slides.length - slidesPerView) {\n      swiper.loopFix();\n      slideToIndex = $wrapperEl.children(`.${params.slideClass}[data-swiper-slide-index=\"${realIndex}\"]:not(.${params.slideDuplicateClass})`).eq(0).index();\n      nextTick(() => {\n        swiper.slideTo(slideToIndex);\n      });\n    } else {\n      swiper.slideTo(slideToIndex);\n    }\n  } else {\n    swiper.slideTo(slideToIndex);\n  }\n}", "import slideTo from './slideTo.js';\nimport slideToLoop from './slideToLoop.js';\nimport slideNext from './slideNext.js';\nimport slidePrev from './slidePrev.js';\nimport slideReset from './slideReset.js';\nimport slideToClosest from './slideToClosest.js';\nimport slideToClickedSlide from './slideToClickedSlide.js';\nexport default {\n  slideTo,\n  slideToLoop,\n  slideNext,\n  slidePrev,\n  slideReset,\n  slideToClosest,\n  slideToClickedSlide\n};", "import { getDocument } from 'ssr-window';\nimport $ from '../../shared/dom.js';\nexport default function loopCreate() {\n  const swiper = this;\n  const document = getDocument();\n  const {\n    params,\n    $wrapperEl\n  } = swiper; // Remove duplicated slides\n\n  const $selector = $wrapperEl.children().length > 0 ? $($wrapperEl.children()[0].parentNode) : $wrapperEl;\n  $selector.children(`.${params.slideClass}.${params.slideDuplicateClass}`).remove();\n  let slides = $selector.children(`.${params.slideClass}`);\n\n  if (params.loopFillGroupWithBlank) {\n    const blankSlidesNum = params.slidesPerGroup - slides.length % params.slidesPerGroup;\n\n    if (blankSlidesNum !== params.slidesPerGroup) {\n      for (let i = 0; i < blankSlidesNum; i += 1) {\n        const blankNode = $(document.createElement('div')).addClass(`${params.slideClass} ${params.slideBlankClass}`);\n        $selector.append(blankNode);\n      }\n\n      slides = $selector.children(`.${params.slideClass}`);\n    }\n  }\n\n  if (params.slidesPerView === 'auto' && !params.loopedSlides) params.loopedSlides = slides.length;\n  swiper.loopedSlides = Math.ceil(parseFloat(params.loopedSlides || params.slidesPerView, 10));\n  swiper.loopedSlides += params.loopAdditionalSlides;\n\n  if (swiper.loopedSlides > slides.length && swiper.params.loopedSlidesLimit) {\n    swiper.loopedSlides = slides.length;\n  }\n\n  const prependSlides = [];\n  const appendSlides = [];\n  slides.each((el, index) => {\n    $(el).attr('data-swiper-slide-index', index);\n  });\n\n  for (let i = 0; i < swiper.loopedSlides; i += 1) {\n    const index = i - Math.floor(i / slides.length) * slides.length;\n    appendSlides.push(slides.eq(index)[0]);\n    prependSlides.unshift(slides.eq(slides.length - index - 1)[0]);\n  }\n\n  for (let i = 0; i < appendSlides.length; i += 1) {\n    $selector.append($(appendSlides[i].cloneNode(true)).addClass(params.slideDuplicateClass));\n  }\n\n  for (let i = prependSlides.length - 1; i >= 0; i -= 1) {\n    $selector.prepend($(prependSlides[i].cloneNode(true)).addClass(params.slideDuplicateClass));\n  }\n}", "export default function loopFix() {\n  const swiper = this;\n  swiper.emit('beforeLoopFix');\n  const {\n    activeIndex,\n    slides,\n    loopedSlides,\n    allowSlidePrev,\n    allowSlideNext,\n    snapGrid,\n    rtlTranslate: rtl\n  } = swiper;\n  let newIndex;\n  swiper.allowSlidePrev = true;\n  swiper.allowSlideNext = true;\n  const snapTranslate = -snapGrid[activeIndex];\n  const diff = snapTranslate - swiper.getTranslate(); // Fix For Negative Oversliding\n\n  if (activeIndex < loopedSlides) {\n    newIndex = slides.length - loopedSlides * 3 + activeIndex;\n    newIndex += loopedSlides;\n    const slideChanged = swiper.slideTo(newIndex, 0, false, true);\n\n    if (slideChanged && diff !== 0) {\n      swiper.setTranslate((rtl ? -swiper.translate : swiper.translate) - diff);\n    }\n  } else if (activeIndex >= slides.length - loopedSlides) {\n    // Fix For Positive Oversliding\n    newIndex = -slides.length + activeIndex + loopedSlides;\n    newIndex += loopedSlides;\n    const slideChanged = swiper.slideTo(newIndex, 0, false, true);\n\n    if (slideChanged && diff !== 0) {\n      swiper.setTranslate((rtl ? -swiper.translate : swiper.translate) - diff);\n    }\n  }\n\n  swiper.allowSlidePrev = allowSlidePrev;\n  swiper.allowSlideNext = allowSlideNext;\n  swiper.emit('loopFix');\n}", "export default function loopDestroy() {\n  const swiper = this;\n  const {\n    $wrapperEl,\n    params,\n    slides\n  } = swiper;\n  $wrapperEl.children(`.${params.slideClass}.${params.slideDuplicateClass},.${params.slideClass}.${params.slideBlankClass}`).remove();\n  slides.removeAttr('data-swiper-slide-index');\n}", "import loopCreate from './loopCreate.js';\nimport loopFix from './loopFix.js';\nimport loopDestroy from './loopDestroy.js';\nexport default {\n  loopCreate,\n  loopFix,\n  loopDestroy\n};", "export default function setGrabCursor(moving) {\n  const swiper = this;\n  if (swiper.support.touch || !swiper.params.simulateTouch || swiper.params.watchOverflow && swiper.isLocked || swiper.params.cssMode) return;\n  const el = swiper.params.touchEventsTarget === 'container' ? swiper.el : swiper.wrapperEl;\n  el.style.cursor = 'move';\n  el.style.cursor = moving ? 'grabbing' : 'grab';\n}", "export default function unsetGrabCursor() {\n  const swiper = this;\n\n  if (swiper.support.touch || swiper.params.watchOverflow && swiper.isLocked || swiper.params.cssMode) {\n    return;\n  }\n\n  swiper[swiper.params.touchEventsTarget === 'container' ? 'el' : 'wrapperEl'].style.cursor = '';\n}", "import setGrabCursor from './setGrabCursor.js';\nimport unsetGrabCursor from './unsetGrabCursor.js';\nexport default {\n  setGrabCursor,\n  unsetGrabCursor\n};", "import { getWindow, getDocument } from 'ssr-window';\nimport $ from '../../shared/dom.js';\nimport { now } from '../../shared/utils.js'; // Modified from https://stackoverflow.com/questions/54520554/custom-element-getrootnode-closest-function-crossing-multiple-parent-shadowd\n\nfunction closestElement(selector, base) {\n  if (base === void 0) {\n    base = this;\n  }\n\n  function __closestFrom(el) {\n    if (!el || el === getDocument() || el === getWindow()) return null;\n    if (el.assignedSlot) el = el.assignedSlot;\n    const found = el.closest(selector);\n\n    if (!found && !el.getRootNode) {\n      return null;\n    }\n\n    return found || __closestFrom(el.getRootNode().host);\n  }\n\n  return __closestFrom(base);\n}\n\nexport default function onTouchStart(event) {\n  const swiper = this;\n  const document = getDocument();\n  const window = getWindow();\n  const data = swiper.touchEventsData;\n  const {\n    params,\n    touches,\n    enabled\n  } = swiper;\n  if (!enabled) return;\n\n  if (swiper.animating && params.preventInteractionOnTransition) {\n    return;\n  }\n\n  if (!swiper.animating && params.cssMode && params.loop) {\n    swiper.loopFix();\n  }\n\n  let e = event;\n  if (e.originalEvent) e = e.originalEvent;\n  let $targetEl = $(e.target);\n\n  if (params.touchEventsTarget === 'wrapper') {\n    if (!$targetEl.closest(swiper.wrapperEl).length) return;\n  }\n\n  data.isTouchEvent = e.type === 'touchstart';\n  if (!data.isTouchEvent && 'which' in e && e.which === 3) return;\n  if (!data.isTouchEvent && 'button' in e && e.button > 0) return;\n  if (data.isTouched && data.isMoved) return; // change target el for shadow root component\n\n  const swipingClassHasValue = !!params.noSwipingClass && params.noSwipingClass !== '';\n\n  if (swipingClassHasValue && e.target && e.target.shadowRoot && event.path && event.path[0]) {\n    $targetEl = $(event.path[0]);\n  }\n\n  const noSwipingSelector = params.noSwipingSelector ? params.noSwipingSelector : `.${params.noSwipingClass}`;\n  const isTargetShadow = !!(e.target && e.target.shadowRoot); // use closestElement for shadow root element to get the actual closest for nested shadow root element\n\n  if (params.noSwiping && (isTargetShadow ? closestElement(noSwipingSelector, $targetEl[0]) : $targetEl.closest(noSwipingSelector)[0])) {\n    swiper.allowClick = true;\n    return;\n  }\n\n  if (params.swipeHandler) {\n    if (!$targetEl.closest(params.swipeHandler)[0]) return;\n  }\n\n  touches.currentX = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;\n  touches.currentY = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;\n  const startX = touches.currentX;\n  const startY = touches.currentY; // Do NOT start if iOS edge swipe is detected. Otherwise iOS app cannot swipe-to-go-back anymore\n\n  const edgeSwipeDetection = params.edgeSwipeDetection || params.iOSEdgeSwipeDetection;\n  const edgeSwipeThreshold = params.edgeSwipeThreshold || params.iOSEdgeSwipeThreshold;\n\n  if (edgeSwipeDetection && (startX <= edgeSwipeThreshold || startX >= window.innerWidth - edgeSwipeThreshold)) {\n    if (edgeSwipeDetection === 'prevent') {\n      event.preventDefault();\n    } else {\n      return;\n    }\n  }\n\n  Object.assign(data, {\n    isTouched: true,\n    isMoved: false,\n    allowTouchCallbacks: true,\n    isScrolling: undefined,\n    startMoving: undefined\n  });\n  touches.startX = startX;\n  touches.startY = startY;\n  data.touchStartTime = now();\n  swiper.allowClick = true;\n  swiper.updateSize();\n  swiper.swipeDirection = undefined;\n  if (params.threshold > 0) data.allowThresholdMove = false;\n\n  if (e.type !== 'touchstart') {\n    let preventDefault = true;\n\n    if ($targetEl.is(data.focusableElements)) {\n      preventDefault = false;\n\n      if ($targetEl[0].nodeName === 'SELECT') {\n        data.isTouched = false;\n      }\n    }\n\n    if (document.activeElement && $(document.activeElement).is(data.focusableElements) && document.activeElement !== $targetEl[0]) {\n      document.activeElement.blur();\n    }\n\n    const shouldPreventDefault = preventDefault && swiper.allowTouchMove && params.touchStartPreventDefault;\n\n    if ((params.touchStartForcePreventDefault || shouldPreventDefault) && !$targetEl[0].isContentEditable) {\n      e.preventDefault();\n    }\n  }\n\n  if (swiper.params.freeMode && swiper.params.freeMode.enabled && swiper.freeMode && swiper.animating && !params.cssMode) {\n    swiper.freeMode.onTouchStart();\n  }\n\n  swiper.emit('touchStart', e);\n}", "import { getDocument } from 'ssr-window';\nimport $ from '../../shared/dom.js';\nimport { now } from '../../shared/utils.js';\nexport default function onTouchMove(event) {\n  const document = getDocument();\n  const swiper = this;\n  const data = swiper.touchEventsData;\n  const {\n    params,\n    touches,\n    rtlTranslate: rtl,\n    enabled\n  } = swiper;\n  if (!enabled) return;\n  let e = event;\n  if (e.originalEvent) e = e.originalEvent;\n\n  if (!data.isTouched) {\n    if (data.startMoving && data.isScrolling) {\n      swiper.emit('touchMoveOpposite', e);\n    }\n\n    return;\n  }\n\n  if (data.isTouchEvent && e.type !== 'touchmove') return;\n  const targetTouch = e.type === 'touchmove' && e.targetTouches && (e.targetTouches[0] || e.changedTouches[0]);\n  const pageX = e.type === 'touchmove' ? targetTouch.pageX : e.pageX;\n  const pageY = e.type === 'touchmove' ? targetTouch.pageY : e.pageY;\n\n  if (e.preventedByNestedSwiper) {\n    touches.startX = pageX;\n    touches.startY = pageY;\n    return;\n  }\n\n  if (!swiper.allowTouchMove) {\n    if (!$(e.target).is(data.focusableElements)) {\n      swiper.allowClick = false;\n    }\n\n    if (data.isTouched) {\n      Object.assign(touches, {\n        startX: pageX,\n        startY: pageY,\n        currentX: pageX,\n        currentY: pageY\n      });\n      data.touchStartTime = now();\n    }\n\n    return;\n  }\n\n  if (data.isTouchEvent && params.touchReleaseOnEdges && !params.loop) {\n    if (swiper.isVertical()) {\n      // Vertical\n      if (pageY < touches.startY && swiper.translate <= swiper.maxTranslate() || pageY > touches.startY && swiper.translate >= swiper.minTranslate()) {\n        data.isTouched = false;\n        data.isMoved = false;\n        return;\n      }\n    } else if (pageX < touches.startX && swiper.translate <= swiper.maxTranslate() || pageX > touches.startX && swiper.translate >= swiper.minTranslate()) {\n      return;\n    }\n  }\n\n  if (data.isTouchEvent && document.activeElement) {\n    if (e.target === document.activeElement && $(e.target).is(data.focusableElements)) {\n      data.isMoved = true;\n      swiper.allowClick = false;\n      return;\n    }\n  }\n\n  if (data.allowTouchCallbacks) {\n    swiper.emit('touchMove', e);\n  }\n\n  if (e.targetTouches && e.targetTouches.length > 1) return;\n  touches.currentX = pageX;\n  touches.currentY = pageY;\n  const diffX = touches.currentX - touches.startX;\n  const diffY = touches.currentY - touches.startY;\n  if (swiper.params.threshold && Math.sqrt(diffX ** 2 + diffY ** 2) < swiper.params.threshold) return;\n\n  if (typeof data.isScrolling === 'undefined') {\n    let touchAngle;\n\n    if (swiper.isHorizontal() && touches.currentY === touches.startY || swiper.isVertical() && touches.currentX === touches.startX) {\n      data.isScrolling = false;\n    } else {\n      // eslint-disable-next-line\n      if (diffX * diffX + diffY * diffY >= 25) {\n        touchAngle = Math.atan2(Math.abs(diffY), Math.abs(diffX)) * 180 / Math.PI;\n        data.isScrolling = swiper.isHorizontal() ? touchAngle > params.touchAngle : 90 - touchAngle > params.touchAngle;\n      }\n    }\n  }\n\n  if (data.isScrolling) {\n    swiper.emit('touchMoveOpposite', e);\n  }\n\n  if (typeof data.startMoving === 'undefined') {\n    if (touches.currentX !== touches.startX || touches.currentY !== touches.startY) {\n      data.startMoving = true;\n    }\n  }\n\n  if (data.isScrolling) {\n    data.isTouched = false;\n    return;\n  }\n\n  if (!data.startMoving) {\n    return;\n  }\n\n  swiper.allowClick = false;\n\n  if (!params.cssMode && e.cancelable) {\n    e.preventDefault();\n  }\n\n  if (params.touchMoveStopPropagation && !params.nested) {\n    e.stopPropagation();\n  }\n\n  if (!data.isMoved) {\n    if (params.loop && !params.cssMode) {\n      swiper.loopFix();\n    }\n\n    data.startTranslate = swiper.getTranslate();\n    swiper.setTransition(0);\n\n    if (swiper.animating) {\n      swiper.$wrapperEl.trigger('webkitTransitionEnd transitionend');\n    }\n\n    data.allowMomentumBounce = false; // Grab Cursor\n\n    if (params.grabCursor && (swiper.allowSlideNext === true || swiper.allowSlidePrev === true)) {\n      swiper.setGrabCursor(true);\n    }\n\n    swiper.emit('sliderFirstMove', e);\n  }\n\n  swiper.emit('sliderMove', e);\n  data.isMoved = true;\n  let diff = swiper.isHorizontal() ? diffX : diffY;\n  touches.diff = diff;\n  diff *= params.touchRatio;\n  if (rtl) diff = -diff;\n  swiper.swipeDirection = diff > 0 ? 'prev' : 'next';\n  data.currentTranslate = diff + data.startTranslate;\n  let disableParentSwiper = true;\n  let resistanceRatio = params.resistanceRatio;\n\n  if (params.touchReleaseOnEdges) {\n    resistanceRatio = 0;\n  }\n\n  if (diff > 0 && data.currentTranslate > swiper.minTranslate()) {\n    disableParentSwiper = false;\n    if (params.resistance) data.currentTranslate = swiper.minTranslate() - 1 + (-swiper.minTranslate() + data.startTranslate + diff) ** resistanceRatio;\n  } else if (diff < 0 && data.currentTranslate < swiper.maxTranslate()) {\n    disableParentSwiper = false;\n    if (params.resistance) data.currentTranslate = swiper.maxTranslate() + 1 - (swiper.maxTranslate() - data.startTranslate - diff) ** resistanceRatio;\n  }\n\n  if (disableParentSwiper) {\n    e.preventedByNestedSwiper = true;\n  } // Directions locks\n\n\n  if (!swiper.allowSlideNext && swiper.swipeDirection === 'next' && data.currentTranslate < data.startTranslate) {\n    data.currentTranslate = data.startTranslate;\n  }\n\n  if (!swiper.allowSlidePrev && swiper.swipeDirection === 'prev' && data.currentTranslate > data.startTranslate) {\n    data.currentTranslate = data.startTranslate;\n  }\n\n  if (!swiper.allowSlidePrev && !swiper.allowSlideNext) {\n    data.currentTranslate = data.startTranslate;\n  } // Threshold\n\n\n  if (params.threshold > 0) {\n    if (Math.abs(diff) > params.threshold || data.allowThresholdMove) {\n      if (!data.allowThresholdMove) {\n        data.allowThresholdMove = true;\n        touches.startX = touches.currentX;\n        touches.startY = touches.currentY;\n        data.currentTranslate = data.startTranslate;\n        touches.diff = swiper.isHorizontal() ? touches.currentX - touches.startX : touches.currentY - touches.startY;\n        return;\n      }\n    } else {\n      data.currentTranslate = data.startTranslate;\n      return;\n    }\n  }\n\n  if (!params.followFinger || params.cssMode) return; // Update active index in free mode\n\n  if (params.freeMode && params.freeMode.enabled && swiper.freeMode || params.watchSlidesProgress) {\n    swiper.updateActiveIndex();\n    swiper.updateSlidesClasses();\n  }\n\n  if (swiper.params.freeMode && params.freeMode.enabled && swiper.freeMode) {\n    swiper.freeMode.onTouchMove();\n  } // Update progress\n\n\n  swiper.updateProgress(data.currentTranslate); // Update translate\n\n  swiper.setTranslate(data.currentTranslate);\n}", "import { now, nextTick } from '../../shared/utils.js';\nexport default function onTouchEnd(event) {\n  const swiper = this;\n  const data = swiper.touchEventsData;\n  const {\n    params,\n    touches,\n    rtlTranslate: rtl,\n    slidesGrid,\n    enabled\n  } = swiper;\n  if (!enabled) return;\n  let e = event;\n  if (e.originalEvent) e = e.originalEvent;\n\n  if (data.allowTouchCallbacks) {\n    swiper.emit('touchEnd', e);\n  }\n\n  data.allowTouchCallbacks = false;\n\n  if (!data.isTouched) {\n    if (data.isMoved && params.grabCursor) {\n      swiper.setGrabCursor(false);\n    }\n\n    data.isMoved = false;\n    data.startMoving = false;\n    return;\n  } // Return Grab Cursor\n\n\n  if (params.grabCursor && data.isMoved && data.isTouched && (swiper.allowSlideNext === true || swiper.allowSlidePrev === true)) {\n    swiper.setGrabCursor(false);\n  } // Time diff\n\n\n  const touchEndTime = now();\n  const timeDiff = touchEndTime - data.touchStartTime; // Tap, doubleTap, Click\n\n  if (swiper.allowClick) {\n    const pathTree = e.path || e.composedPath && e.composedPath();\n    swiper.updateClickedSlide(pathTree && pathTree[0] || e.target);\n    swiper.emit('tap click', e);\n\n    if (timeDiff < 300 && touchEndTime - data.lastClickTime < 300) {\n      swiper.emit('doubleTap doubleClick', e);\n    }\n  }\n\n  data.lastClickTime = now();\n  nextTick(() => {\n    if (!swiper.destroyed) swiper.allowClick = true;\n  });\n\n  if (!data.isTouched || !data.isMoved || !swiper.swipeDirection || touches.diff === 0 || data.currentTranslate === data.startTranslate) {\n    data.isTouched = false;\n    data.isMoved = false;\n    data.startMoving = false;\n    return;\n  }\n\n  data.isTouched = false;\n  data.isMoved = false;\n  data.startMoving = false;\n  let currentPos;\n\n  if (params.followFinger) {\n    currentPos = rtl ? swiper.translate : -swiper.translate;\n  } else {\n    currentPos = -data.currentTranslate;\n  }\n\n  if (params.cssMode) {\n    return;\n  }\n\n  if (swiper.params.freeMode && params.freeMode.enabled) {\n    swiper.freeMode.onTouchEnd({\n      currentPos\n    });\n    return;\n  } // Find current slide\n\n\n  let stopIndex = 0;\n  let groupSize = swiper.slidesSizesGrid[0];\n\n  for (let i = 0; i < slidesGrid.length; i += i < params.slidesPerGroupSkip ? 1 : params.slidesPerGroup) {\n    const increment = i < params.slidesPerGroupSkip - 1 ? 1 : params.slidesPerGroup;\n\n    if (typeof slidesGrid[i + increment] !== 'undefined') {\n      if (currentPos >= slidesGrid[i] && currentPos < slidesGrid[i + increment]) {\n        stopIndex = i;\n        groupSize = slidesGrid[i + increment] - slidesGrid[i];\n      }\n    } else if (currentPos >= slidesGrid[i]) {\n      stopIndex = i;\n      groupSize = slidesGrid[slidesGrid.length - 1] - slidesGrid[slidesGrid.length - 2];\n    }\n  }\n\n  let rewindFirstIndex = null;\n  let rewindLastIndex = null;\n\n  if (params.rewind) {\n    if (swiper.isBeginning) {\n      rewindLastIndex = swiper.params.virtual && swiper.params.virtual.enabled && swiper.virtual ? swiper.virtual.slides.length - 1 : swiper.slides.length - 1;\n    } else if (swiper.isEnd) {\n      rewindFirstIndex = 0;\n    }\n  } // Find current slide size\n\n\n  const ratio = (currentPos - slidesGrid[stopIndex]) / groupSize;\n  const increment = stopIndex < params.slidesPerGroupSkip - 1 ? 1 : params.slidesPerGroup;\n\n  if (timeDiff > params.longSwipesMs) {\n    // Long touches\n    if (!params.longSwipes) {\n      swiper.slideTo(swiper.activeIndex);\n      return;\n    }\n\n    if (swiper.swipeDirection === 'next') {\n      if (ratio >= params.longSwipesRatio) swiper.slideTo(params.rewind && swiper.isEnd ? rewindFirstIndex : stopIndex + increment);else swiper.slideTo(stopIndex);\n    }\n\n    if (swiper.swipeDirection === 'prev') {\n      if (ratio > 1 - params.longSwipesRatio) {\n        swiper.slideTo(stopIndex + increment);\n      } else if (rewindLastIndex !== null && ratio < 0 && Math.abs(ratio) > params.longSwipesRatio) {\n        swiper.slideTo(rewindLastIndex);\n      } else {\n        swiper.slideTo(stopIndex);\n      }\n    }\n  } else {\n    // Short swipes\n    if (!params.shortSwipes) {\n      swiper.slideTo(swiper.activeIndex);\n      return;\n    }\n\n    const isNavButtonTarget = swiper.navigation && (e.target === swiper.navigation.nextEl || e.target === swiper.navigation.prevEl);\n\n    if (!isNavButtonTarget) {\n      if (swiper.swipeDirection === 'next') {\n        swiper.slideTo(rewindFirstIndex !== null ? rewindFirstIndex : stopIndex + increment);\n      }\n\n      if (swiper.swipeDirection === 'prev') {\n        swiper.slideTo(rewindLastIndex !== null ? rewindLastIndex : stopIndex);\n      }\n    } else if (e.target === swiper.navigation.nextEl) {\n      swiper.slideTo(stopIndex + increment);\n    } else {\n      swiper.slideTo(stopIndex);\n    }\n  }\n}", "export default function onResize() {\n  const swiper = this;\n  const {\n    params,\n    el\n  } = swiper;\n  if (el && el.offsetWidth === 0) return; // Breakpoints\n\n  if (params.breakpoints) {\n    swiper.setBreakpoint();\n  } // Save locks\n\n\n  const {\n    allowSlideNext,\n    allowSlidePrev,\n    snapGrid\n  } = swiper; // Disable locks on resize\n\n  swiper.allowSlideNext = true;\n  swiper.allowSlidePrev = true;\n  swiper.updateSize();\n  swiper.updateSlides();\n  swiper.updateSlidesClasses();\n\n  if ((params.slidesPerView === 'auto' || params.slidesPerView > 1) && swiper.isEnd && !swiper.isBeginning && !swiper.params.centeredSlides) {\n    swiper.slideTo(swiper.slides.length - 1, 0, false, true);\n  } else {\n    swiper.slideTo(swiper.activeIndex, 0, false, true);\n  }\n\n  if (swiper.autoplay && swiper.autoplay.running && swiper.autoplay.paused) {\n    swiper.autoplay.run();\n  } // Return locks after resize\n\n\n  swiper.allowSlidePrev = allowSlidePrev;\n  swiper.allowSlideNext = allowSlideNext;\n\n  if (swiper.params.watchOverflow && snapGrid !== swiper.snapGrid) {\n    swiper.checkOverflow();\n  }\n}", "export default function onClick(e) {\n  const swiper = this;\n  if (!swiper.enabled) return;\n\n  if (!swiper.allowClick) {\n    if (swiper.params.preventClicks) e.preventDefault();\n\n    if (swiper.params.preventClicksPropagation && swiper.animating) {\n      e.stopPropagation();\n      e.stopImmediatePropagation();\n    }\n  }\n}", "export default function onScroll() {\n  const swiper = this;\n  const {\n    wrapperEl,\n    rtlTranslate,\n    enabled\n  } = swiper;\n  if (!enabled) return;\n  swiper.previousTranslate = swiper.translate;\n\n  if (swiper.isHorizontal()) {\n    swiper.translate = -wrapperEl.scrollLeft;\n  } else {\n    swiper.translate = -wrapperEl.scrollTop;\n  } // eslint-disable-next-line\n\n\n  if (swiper.translate === 0) swiper.translate = 0;\n  swiper.updateActiveIndex();\n  swiper.updateSlidesClasses();\n  let newProgress;\n  const translatesDiff = swiper.maxTranslate() - swiper.minTranslate();\n\n  if (translatesDiff === 0) {\n    newProgress = 0;\n  } else {\n    newProgress = (swiper.translate - swiper.minTranslate()) / translatesDiff;\n  }\n\n  if (newProgress !== swiper.progress) {\n    swiper.updateProgress(rtlTranslate ? -swiper.translate : swiper.translate);\n  }\n\n  swiper.emit('setTranslate', swiper.translate, false);\n}", "import { getDocument } from 'ssr-window';\nimport onTouchStart from './onTouchStart.js';\nimport onTouchMove from './onTouchMove.js';\nimport onTouchEnd from './onTouchEnd.js';\nimport onResize from './onResize.js';\nimport onClick from './onClick.js';\nimport onScroll from './onScroll.js';\nlet dummyEventAttached = false;\n\nfunction dummyEventListener() {}\n\nconst events = (swiper, method) => {\n  const document = getDocument();\n  const {\n    params,\n    touchEvents,\n    el,\n    wrapperEl,\n    device,\n    support\n  } = swiper;\n  const capture = !!params.nested;\n  const domMethod = method === 'on' ? 'addEventListener' : 'removeEventListener';\n  const swiperMethod = method; // Touch Events\n\n  if (!support.touch) {\n    el[domMethod](touchEvents.start, swiper.onTouchStart, false);\n    document[domMethod](touchEvents.move, swiper.onTouchMove, capture);\n    document[domMethod](touchEvents.end, swiper.onTouchEnd, false);\n  } else {\n    const passiveListener = touchEvents.start === 'touchstart' && support.passiveListener && params.passiveListeners ? {\n      passive: true,\n      capture: false\n    } : false;\n    el[domMethod](touchEvents.start, swiper.onTouchStart, passiveListener);\n    el[domMethod](touchEvents.move, swiper.onTouchMove, support.passiveListener ? {\n      passive: false,\n      capture\n    } : capture);\n    el[domMethod](touchEvents.end, swiper.onTouchEnd, passiveListener);\n\n    if (touchEvents.cancel) {\n      el[domMethod](touchEvents.cancel, swiper.onTouchEnd, passiveListener);\n    }\n  } // Prevent Links Clicks\n\n\n  if (params.preventClicks || params.preventClicksPropagation) {\n    el[domMethod]('click', swiper.onClick, true);\n  }\n\n  if (params.cssMode) {\n    wrapperEl[domMethod]('scroll', swiper.onScroll);\n  } // Resize handler\n\n\n  if (params.updateOnWindowResize) {\n    swiper[swiperMethod](device.ios || device.android ? 'resize orientationchange observerUpdate' : 'resize observerUpdate', onResize, true);\n  } else {\n    swiper[swiperMethod]('observerUpdate', onResize, true);\n  }\n};\n\nfunction attachEvents() {\n  const swiper = this;\n  const document = getDocument();\n  const {\n    params,\n    support\n  } = swiper;\n  swiper.onTouchStart = onTouchStart.bind(swiper);\n  swiper.onTouchMove = onTouchMove.bind(swiper);\n  swiper.onTouchEnd = onTouchEnd.bind(swiper);\n\n  if (params.cssMode) {\n    swiper.onScroll = onScroll.bind(swiper);\n  }\n\n  swiper.onClick = onClick.bind(swiper);\n\n  if (support.touch && !dummyEventAttached) {\n    document.addEventListener('touchstart', dummyEventListener);\n    dummyEventAttached = true;\n  }\n\n  events(swiper, 'on');\n}\n\nfunction detachEvents() {\n  const swiper = this;\n  events(swiper, 'off');\n}\n\nexport default {\n  attachEvents,\n  detachEvents\n};", "import { extend } from '../../shared/utils.js';\n\nconst isGridEnabled = (swiper, params) => {\n  return swiper.grid && params.grid && params.grid.rows > 1;\n};\n\nexport default function setBreakpoint() {\n  const swiper = this;\n  const {\n    activeIndex,\n    initialized,\n    loopedSlides = 0,\n    params,\n    $el\n  } = swiper;\n  const breakpoints = params.breakpoints;\n  if (!breakpoints || breakpoints && Object.keys(breakpoints).length === 0) return; // Get breakpoint for window width and update parameters\n\n  const breakpoint = swiper.getBreakpoint(breakpoints, swiper.params.breakpointsBase, swiper.el);\n  if (!breakpoint || swiper.currentBreakpoint === breakpoint) return;\n  const breakpointOnlyParams = breakpoint in breakpoints ? breakpoints[breakpoint] : undefined;\n  const breakpointParams = breakpointOnlyParams || swiper.originalParams;\n  const wasMultiRow = isGridEnabled(swiper, params);\n  const isMultiRow = isGridEnabled(swiper, breakpointParams);\n  const wasEnabled = params.enabled;\n\n  if (wasMultiRow && !isMultiRow) {\n    $el.removeClass(`${params.containerModifierClass}grid ${params.containerModifierClass}grid-column`);\n    swiper.emitContainerClasses();\n  } else if (!wasMultiRow && isMultiRow) {\n    $el.addClass(`${params.containerModifierClass}grid`);\n\n    if (breakpointParams.grid.fill && breakpointParams.grid.fill === 'column' || !breakpointParams.grid.fill && params.grid.fill === 'column') {\n      $el.addClass(`${params.containerModifierClass}grid-column`);\n    }\n\n    swiper.emitContainerClasses();\n  } // Toggle navigation, pagination, scrollbar\n\n\n  ['navigation', 'pagination', 'scrollbar'].forEach(prop => {\n    const wasModuleEnabled = params[prop] && params[prop].enabled;\n    const isModuleEnabled = breakpointParams[prop] && breakpointParams[prop].enabled;\n\n    if (wasModuleEnabled && !isModuleEnabled) {\n      swiper[prop].disable();\n    }\n\n    if (!wasModuleEnabled && isModuleEnabled) {\n      swiper[prop].enable();\n    }\n  });\n  const directionChanged = breakpointParams.direction && breakpointParams.direction !== params.direction;\n  const needsReLoop = params.loop && (breakpointParams.slidesPerView !== params.slidesPerView || directionChanged);\n\n  if (directionChanged && initialized) {\n    swiper.changeDirection();\n  }\n\n  extend(swiper.params, breakpointParams);\n  const isEnabled = swiper.params.enabled;\n  Object.assign(swiper, {\n    allowTouchMove: swiper.params.allowTouchMove,\n    allowSlideNext: swiper.params.allowSlideNext,\n    allowSlidePrev: swiper.params.allowSlidePrev\n  });\n\n  if (wasEnabled && !isEnabled) {\n    swiper.disable();\n  } else if (!wasEnabled && isEnabled) {\n    swiper.enable();\n  }\n\n  swiper.currentBreakpoint = breakpoint;\n  swiper.emit('_beforeBreakpoint', breakpointParams);\n\n  if (needsReLoop && initialized) {\n    swiper.loopDestroy();\n    swiper.loopCreate();\n    swiper.updateSlides();\n    swiper.slideTo(activeIndex - loopedSlides + swiper.loopedSlides, 0, false);\n  }\n\n  swiper.emit('breakpoint', breakpointParams);\n}", "import { getWindow } from 'ssr-window';\nexport default function getBreakpoint(breakpoints, base, containerEl) {\n  if (base === void 0) {\n    base = 'window';\n  }\n\n  if (!breakpoints || base === 'container' && !containerEl) return undefined;\n  let breakpoint = false;\n  const window = getWindow();\n  const currentHeight = base === 'window' ? window.innerHeight : containerEl.clientHeight;\n  const points = Object.keys(breakpoints).map(point => {\n    if (typeof point === 'string' && point.indexOf('@') === 0) {\n      const minRatio = parseFloat(point.substr(1));\n      const value = currentHeight * minRatio;\n      return {\n        value,\n        point\n      };\n    }\n\n    return {\n      value: point,\n      point\n    };\n  });\n  points.sort((a, b) => parseInt(a.value, 10) - parseInt(b.value, 10));\n\n  for (let i = 0; i < points.length; i += 1) {\n    const {\n      point,\n      value\n    } = points[i];\n\n    if (base === 'window') {\n      if (window.matchMedia(`(min-width: ${value}px)`).matches) {\n        breakpoint = point;\n      }\n    } else if (value <= containerEl.clientWidth) {\n      breakpoint = point;\n    }\n  }\n\n  return breakpoint || 'max';\n}", "import setBreakpoint from './setBreakpoint.js';\nimport getBreakpoint from './getBreakpoint.js';\nexport default {\n  setBreakpoint,\n  getBreakpoint\n};", "function prepareClasses(entries, prefix) {\n  const resultClasses = [];\n  entries.forEach(item => {\n    if (typeof item === 'object') {\n      Object.keys(item).forEach(classNames => {\n        if (item[classNames]) {\n          resultClasses.push(prefix + classNames);\n        }\n      });\n    } else if (typeof item === 'string') {\n      resultClasses.push(prefix + item);\n    }\n  });\n  return resultClasses;\n}\n\nexport default function addClasses() {\n  const swiper = this;\n  const {\n    classNames,\n    params,\n    rtl,\n    $el,\n    device,\n    support\n  } = swiper; // prettier-ignore\n\n  const suffixes = prepareClasses(['initialized', params.direction, {\n    'pointer-events': !support.touch\n  }, {\n    'free-mode': swiper.params.freeMode && params.freeMode.enabled\n  }, {\n    'autoheight': params.autoHeight\n  }, {\n    'rtl': rtl\n  }, {\n    'grid': params.grid && params.grid.rows > 1\n  }, {\n    'grid-column': params.grid && params.grid.rows > 1 && params.grid.fill === 'column'\n  }, {\n    'android': device.android\n  }, {\n    'ios': device.ios\n  }, {\n    'css-mode': params.cssMode\n  }, {\n    'centered': params.cssMode && params.centeredSlides\n  }, {\n    'watch-progress': params.watchSlidesProgress\n  }], params.containerModifierClass);\n  classNames.push(...suffixes);\n  $el.addClass([...classNames].join(' '));\n  swiper.emitContainerClasses();\n}", "export default function removeClasses() {\n  const swiper = this;\n  const {\n    $el,\n    classNames\n  } = swiper;\n  $el.removeClass(classNames.join(' '));\n  swiper.emitContainerClasses();\n}", "import addClasses from './addClasses.js';\nimport removeClasses from './removeClasses.js';\nexport default {\n  addClasses,\n  removeClasses\n};", "import { getWindow } from 'ssr-window';\nimport $ from '../../shared/dom.js';\nexport default function loadImage(imageEl, src, srcset, sizes, checkForComplete, callback) {\n  const window = getWindow();\n  let image;\n\n  function onReady() {\n    if (callback) callback();\n  }\n\n  const isPicture = $(imageEl).parent('picture')[0];\n\n  if (!isPicture && (!imageEl.complete || !checkForComplete)) {\n    if (src) {\n      image = new window.Image();\n      image.onload = onReady;\n      image.onerror = onReady;\n\n      if (sizes) {\n        image.sizes = sizes;\n      }\n\n      if (srcset) {\n        image.srcset = srcset;\n      }\n\n      if (src) {\n        image.src = src;\n      }\n    } else {\n      onReady();\n    }\n  } else {\n    // image already loaded...\n    onReady();\n  }\n}", "export default function preloadImages() {\n  const swiper = this;\n  swiper.imagesToLoad = swiper.$el.find('img');\n\n  function onReady() {\n    if (typeof swiper === 'undefined' || swiper === null || !swiper || swiper.destroyed) return;\n    if (swiper.imagesLoaded !== undefined) swiper.imagesLoaded += 1;\n\n    if (swiper.imagesLoaded === swiper.imagesToLoad.length) {\n      if (swiper.params.updateOnImagesReady) swiper.update();\n      swiper.emit('imagesReady');\n    }\n  }\n\n  for (let i = 0; i < swiper.imagesToLoad.length; i += 1) {\n    const imageEl = swiper.imagesToLoad[i];\n    swiper.loadImage(imageEl, imageEl.currentSrc || imageEl.getAttribute('src'), imageEl.srcset || imageEl.getAttribute('srcset'), imageEl.sizes || imageEl.getAttribute('sizes'), true, onReady);\n  }\n}", "import loadImage from './loadImage.js';\nimport preloadImages from './preloadImages.js';\nexport default {\n  loadImage,\n  preloadImages\n};", "function checkOverflow() {\n  const swiper = this;\n  const {\n    isLocked: wasLocked,\n    params\n  } = swiper;\n  const {\n    slidesOffsetBefore\n  } = params;\n\n  if (slidesOffsetBefore) {\n    const lastSlideIndex = swiper.slides.length - 1;\n    const lastSlideRightEdge = swiper.slidesGrid[lastSlideIndex] + swiper.slidesSizesGrid[lastSlideIndex] + slidesOffsetBefore * 2;\n    swiper.isLocked = swiper.size > lastSlideRightEdge;\n  } else {\n    swiper.isLocked = swiper.snapGrid.length === 1;\n  }\n\n  if (params.allowSlideNext === true) {\n    swiper.allowSlideNext = !swiper.isLocked;\n  }\n\n  if (params.allowSlidePrev === true) {\n    swiper.allowSlidePrev = !swiper.isLocked;\n  }\n\n  if (wasLocked && wasLocked !== swiper.isLocked) {\n    swiper.isEnd = false;\n  }\n\n  if (wasLocked !== swiper.isLocked) {\n    swiper.emit(swiper.isLocked ? 'lock' : 'unlock');\n  }\n}\n\nexport default {\n  checkOverflow\n};", "export default {\n  init: true,\n  direction: 'horizontal',\n  touchEventsTarget: 'wrapper',\n  initialSlide: 0,\n  speed: 300,\n  cssMode: false,\n  updateOnWindowResize: true,\n  resizeObserver: true,\n  nested: false,\n  createElements: false,\n  enabled: true,\n  focusableElements: 'input, select, option, textarea, button, video, label',\n  // Overrides\n  width: null,\n  height: null,\n  //\n  preventInteractionOnTransition: false,\n  // ssr\n  userAgent: null,\n  url: null,\n  // To support iOS's swipe-to-go-back gesture (when being used in-app).\n  edgeSwipeDetection: false,\n  edgeSwipeThreshold: 20,\n  // Autoheight\n  autoHeight: false,\n  // Set wrapper width\n  setWrapperSize: false,\n  // Virtual Translate\n  virtualTranslate: false,\n  // Effects\n  effect: 'slide',\n  // 'slide' or 'fade' or 'cube' or 'coverflow' or 'flip'\n  // Breakpoints\n  breakpoints: undefined,\n  breakpointsBase: 'window',\n  // Slides grid\n  spaceBetween: 0,\n  slidesPerView: 1,\n  slidesPerGroup: 1,\n  slidesPerGroupSkip: 0,\n  slidesPerGroupAuto: false,\n  centeredSlides: false,\n  centeredSlidesBounds: false,\n  slidesOffsetBefore: 0,\n  // in px\n  slidesOffsetAfter: 0,\n  // in px\n  normalizeSlideIndex: true,\n  centerInsufficientSlides: false,\n  // Disable swiper and hide navigation when container not overflow\n  watchOverflow: true,\n  // Round length\n  roundLengths: false,\n  // Touches\n  touchRatio: 1,\n  touchAngle: 45,\n  simulateTouch: true,\n  shortSwipes: true,\n  longSwipes: true,\n  longSwipesRatio: 0.5,\n  longSwipesMs: 300,\n  followFinger: true,\n  allowTouchMove: true,\n  threshold: 0,\n  touchMoveStopPropagation: false,\n  touchStartPreventDefault: true,\n  touchStartForcePreventDefault: false,\n  touchReleaseOnEdges: false,\n  // Unique Navigation Elements\n  uniqueNavElements: true,\n  // Resistance\n  resistance: true,\n  resistanceRatio: 0.85,\n  // Progress\n  watchSlidesProgress: false,\n  // Cursor\n  grabCursor: false,\n  // Clicks\n  preventClicks: true,\n  preventClicksPropagation: true,\n  slideToClickedSlide: false,\n  // Images\n  preloadImages: true,\n  updateOnImagesReady: true,\n  // loop\n  loop: false,\n  loopAdditionalSlides: 0,\n  loopedSlides: null,\n  loopedSlidesLimit: true,\n  loopFillGroupWithBlank: false,\n  loopPreventsSlide: true,\n  // rewind\n  rewind: false,\n  // Swiping/no swiping\n  allowSlidePrev: true,\n  allowSlideNext: true,\n  swipeHandler: null,\n  // '.swipe-handler',\n  noSwiping: true,\n  noSwipingClass: 'swiper-no-swiping',\n  noSwipingSelector: null,\n  // Passive Listeners\n  passiveListeners: true,\n  maxBackfaceHiddenSlides: 10,\n  // NS\n  containerModifierClass: 'swiper-',\n  // NEW\n  slideClass: 'swiper-slide',\n  slideBlankClass: 'swiper-slide-invisible-blank',\n  slideActiveClass: 'swiper-slide-active',\n  slideDuplicateActiveClass: 'swiper-slide-duplicate-active',\n  slideVisibleClass: 'swiper-slide-visible',\n  slideDuplicateClass: 'swiper-slide-duplicate',\n  slideNextClass: 'swiper-slide-next',\n  slideDuplicateNextClass: 'swiper-slide-duplicate-next',\n  slidePrevClass: 'swiper-slide-prev',\n  slideDuplicatePrevClass: 'swiper-slide-duplicate-prev',\n  wrapperClass: 'swiper-wrapper',\n  // Callbacks\n  runCallbacksOnInit: true,\n  // Internals\n  _emitClasses: false\n};", "import { extend } from '../shared/utils.js';\nexport default function moduleExtendParams(params, allModulesParams) {\n  return function extendParams(obj) {\n    if (obj === void 0) {\n      obj = {};\n    }\n\n    const moduleParamName = Object.keys(obj)[0];\n    const moduleParams = obj[moduleParamName];\n\n    if (typeof moduleParams !== 'object' || moduleParams === null) {\n      extend(allModulesParams, obj);\n      return;\n    }\n\n    if (['navigation', 'pagination', 'scrollbar'].indexOf(moduleParamName) >= 0 && params[moduleParamName] === true) {\n      params[moduleParamName] = {\n        auto: true\n      };\n    }\n\n    if (!(moduleParamName in params && 'enabled' in moduleParams)) {\n      extend(allModulesParams, obj);\n      return;\n    }\n\n    if (params[moduleParamName] === true) {\n      params[moduleParamName] = {\n        enabled: true\n      };\n    }\n\n    if (typeof params[moduleParamName] === 'object' && !('enabled' in params[moduleParamName])) {\n      params[moduleParamName].enabled = true;\n    }\n\n    if (!params[moduleParamName]) params[moduleParamName] = {\n      enabled: false\n    };\n    extend(allModulesParams, obj);\n  };\n}", "/* eslint no-param-reassign: \"off\" */\nimport { getDocument } from 'ssr-window';\nimport $ from '../shared/dom.js';\nimport { extend, now, deleteProps } from '../shared/utils.js';\nimport { getSupport } from '../shared/get-support.js';\nimport { getDevice } from '../shared/get-device.js';\nimport { getBrowser } from '../shared/get-browser.js';\nimport Resize from './modules/resize/resize.js';\nimport Observer from './modules/observer/observer.js';\nimport eventsEmitter from './events-emitter.js';\nimport update from './update/index.js';\nimport translate from './translate/index.js';\nimport transition from './transition/index.js';\nimport slide from './slide/index.js';\nimport loop from './loop/index.js';\nimport grabCursor from './grab-cursor/index.js';\nimport events from './events/index.js';\nimport breakpoints from './breakpoints/index.js';\nimport classes from './classes/index.js';\nimport images from './images/index.js';\nimport checkOverflow from './check-overflow/index.js';\nimport defaults from './defaults.js';\nimport moduleExtendParams from './moduleExtendParams.js';\nconst prototypes = {\n  eventsEmitter,\n  update,\n  translate,\n  transition,\n  slide,\n  loop,\n  grabCursor,\n  events,\n  breakpoints,\n  checkOverflow,\n  classes,\n  images\n};\nconst extendedDefaults = {};\n\nclass Swiper {\n  constructor() {\n    let el;\n    let params;\n\n    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n      args[_key] = arguments[_key];\n    }\n\n    if (args.length === 1 && args[0].constructor && Object.prototype.toString.call(args[0]).slice(8, -1) === 'Object') {\n      params = args[0];\n    } else {\n      [el, params] = args;\n    }\n\n    if (!params) params = {};\n    params = extend({}, params);\n    if (el && !params.el) params.el = el;\n\n    if (params.el && $(params.el).length > 1) {\n      const swipers = [];\n      $(params.el).each(containerEl => {\n        const newParams = extend({}, params, {\n          el: containerEl\n        });\n        swipers.push(new Swiper(newParams));\n      });\n      return swipers;\n    } // Swiper Instance\n\n\n    const swiper = this;\n    swiper.__swiper__ = true;\n    swiper.support = getSupport();\n    swiper.device = getDevice({\n      userAgent: params.userAgent\n    });\n    swiper.browser = getBrowser();\n    swiper.eventsListeners = {};\n    swiper.eventsAnyListeners = [];\n    swiper.modules = [...swiper.__modules__];\n\n    if (params.modules && Array.isArray(params.modules)) {\n      swiper.modules.push(...params.modules);\n    }\n\n    const allModulesParams = {};\n    swiper.modules.forEach(mod => {\n      mod({\n        swiper,\n        extendParams: moduleExtendParams(params, allModulesParams),\n        on: swiper.on.bind(swiper),\n        once: swiper.once.bind(swiper),\n        off: swiper.off.bind(swiper),\n        emit: swiper.emit.bind(swiper)\n      });\n    }); // Extend defaults with modules params\n\n    const swiperParams = extend({}, defaults, allModulesParams); // Extend defaults with passed params\n\n    swiper.params = extend({}, swiperParams, extendedDefaults, params);\n    swiper.originalParams = extend({}, swiper.params);\n    swiper.passedParams = extend({}, params); // add event listeners\n\n    if (swiper.params && swiper.params.on) {\n      Object.keys(swiper.params.on).forEach(eventName => {\n        swiper.on(eventName, swiper.params.on[eventName]);\n      });\n    }\n\n    if (swiper.params && swiper.params.onAny) {\n      swiper.onAny(swiper.params.onAny);\n    } // Save Dom lib\n\n\n    swiper.$ = $; // Extend Swiper\n\n    Object.assign(swiper, {\n      enabled: swiper.params.enabled,\n      el,\n      // Classes\n      classNames: [],\n      // Slides\n      slides: $(),\n      slidesGrid: [],\n      snapGrid: [],\n      slidesSizesGrid: [],\n\n      // isDirection\n      isHorizontal() {\n        return swiper.params.direction === 'horizontal';\n      },\n\n      isVertical() {\n        return swiper.params.direction === 'vertical';\n      },\n\n      // Indexes\n      activeIndex: 0,\n      realIndex: 0,\n      //\n      isBeginning: true,\n      isEnd: false,\n      // Props\n      translate: 0,\n      previousTranslate: 0,\n      progress: 0,\n      velocity: 0,\n      animating: false,\n      // Locks\n      allowSlideNext: swiper.params.allowSlideNext,\n      allowSlidePrev: swiper.params.allowSlidePrev,\n      // Touch Events\n      touchEvents: function touchEvents() {\n        const touch = ['touchstart', 'touchmove', 'touchend', 'touchcancel'];\n        const desktop = ['pointerdown', 'pointermove', 'pointerup'];\n        swiper.touchEventsTouch = {\n          start: touch[0],\n          move: touch[1],\n          end: touch[2],\n          cancel: touch[3]\n        };\n        swiper.touchEventsDesktop = {\n          start: desktop[0],\n          move: desktop[1],\n          end: desktop[2]\n        };\n        return swiper.support.touch || !swiper.params.simulateTouch ? swiper.touchEventsTouch : swiper.touchEventsDesktop;\n      }(),\n      touchEventsData: {\n        isTouched: undefined,\n        isMoved: undefined,\n        allowTouchCallbacks: undefined,\n        touchStartTime: undefined,\n        isScrolling: undefined,\n        currentTranslate: undefined,\n        startTranslate: undefined,\n        allowThresholdMove: undefined,\n        // Form elements to match\n        focusableElements: swiper.params.focusableElements,\n        // Last click time\n        lastClickTime: now(),\n        clickTimeout: undefined,\n        // Velocities\n        velocities: [],\n        allowMomentumBounce: undefined,\n        isTouchEvent: undefined,\n        startMoving: undefined\n      },\n      // Clicks\n      allowClick: true,\n      // Touches\n      allowTouchMove: swiper.params.allowTouchMove,\n      touches: {\n        startX: 0,\n        startY: 0,\n        currentX: 0,\n        currentY: 0,\n        diff: 0\n      },\n      // Images\n      imagesToLoad: [],\n      imagesLoaded: 0\n    });\n    swiper.emit('_swiper'); // Init\n\n    if (swiper.params.init) {\n      swiper.init();\n    } // Return app instance\n\n\n    return swiper;\n  }\n\n  enable() {\n    const swiper = this;\n    if (swiper.enabled) return;\n    swiper.enabled = true;\n\n    if (swiper.params.grabCursor) {\n      swiper.setGrabCursor();\n    }\n\n    swiper.emit('enable');\n  }\n\n  disable() {\n    const swiper = this;\n    if (!swiper.enabled) return;\n    swiper.enabled = false;\n\n    if (swiper.params.grabCursor) {\n      swiper.unsetGrabCursor();\n    }\n\n    swiper.emit('disable');\n  }\n\n  setProgress(progress, speed) {\n    const swiper = this;\n    progress = Math.min(Math.max(progress, 0), 1);\n    const min = swiper.minTranslate();\n    const max = swiper.maxTranslate();\n    const current = (max - min) * progress + min;\n    swiper.translateTo(current, typeof speed === 'undefined' ? 0 : speed);\n    swiper.updateActiveIndex();\n    swiper.updateSlidesClasses();\n  }\n\n  emitContainerClasses() {\n    const swiper = this;\n    if (!swiper.params._emitClasses || !swiper.el) return;\n    const cls = swiper.el.className.split(' ').filter(className => {\n      return className.indexOf('swiper') === 0 || className.indexOf(swiper.params.containerModifierClass) === 0;\n    });\n    swiper.emit('_containerClasses', cls.join(' '));\n  }\n\n  getSlideClasses(slideEl) {\n    const swiper = this;\n    if (swiper.destroyed) return '';\n    return slideEl.className.split(' ').filter(className => {\n      return className.indexOf('swiper-slide') === 0 || className.indexOf(swiper.params.slideClass) === 0;\n    }).join(' ');\n  }\n\n  emitSlidesClasses() {\n    const swiper = this;\n    if (!swiper.params._emitClasses || !swiper.el) return;\n    const updates = [];\n    swiper.slides.each(slideEl => {\n      const classNames = swiper.getSlideClasses(slideEl);\n      updates.push({\n        slideEl,\n        classNames\n      });\n      swiper.emit('_slideClass', slideEl, classNames);\n    });\n    swiper.emit('_slideClasses', updates);\n  }\n\n  slidesPerViewDynamic(view, exact) {\n    if (view === void 0) {\n      view = 'current';\n    }\n\n    if (exact === void 0) {\n      exact = false;\n    }\n\n    const swiper = this;\n    const {\n      params,\n      slides,\n      slidesGrid,\n      slidesSizesGrid,\n      size: swiperSize,\n      activeIndex\n    } = swiper;\n    let spv = 1;\n\n    if (params.centeredSlides) {\n      let slideSize = slides[activeIndex].swiperSlideSize;\n      let breakLoop;\n\n      for (let i = activeIndex + 1; i < slides.length; i += 1) {\n        if (slides[i] && !breakLoop) {\n          slideSize += slides[i].swiperSlideSize;\n          spv += 1;\n          if (slideSize > swiperSize) breakLoop = true;\n        }\n      }\n\n      for (let i = activeIndex - 1; i >= 0; i -= 1) {\n        if (slides[i] && !breakLoop) {\n          slideSize += slides[i].swiperSlideSize;\n          spv += 1;\n          if (slideSize > swiperSize) breakLoop = true;\n        }\n      }\n    } else {\n      // eslint-disable-next-line\n      if (view === 'current') {\n        for (let i = activeIndex + 1; i < slides.length; i += 1) {\n          const slideInView = exact ? slidesGrid[i] + slidesSizesGrid[i] - slidesGrid[activeIndex] < swiperSize : slidesGrid[i] - slidesGrid[activeIndex] < swiperSize;\n\n          if (slideInView) {\n            spv += 1;\n          }\n        }\n      } else {\n        // previous\n        for (let i = activeIndex - 1; i >= 0; i -= 1) {\n          const slideInView = slidesGrid[activeIndex] - slidesGrid[i] < swiperSize;\n\n          if (slideInView) {\n            spv += 1;\n          }\n        }\n      }\n    }\n\n    return spv;\n  }\n\n  update() {\n    const swiper = this;\n    if (!swiper || swiper.destroyed) return;\n    const {\n      snapGrid,\n      params\n    } = swiper; // Breakpoints\n\n    if (params.breakpoints) {\n      swiper.setBreakpoint();\n    }\n\n    swiper.updateSize();\n    swiper.updateSlides();\n    swiper.updateProgress();\n    swiper.updateSlidesClasses();\n\n    function setTranslate() {\n      const translateValue = swiper.rtlTranslate ? swiper.translate * -1 : swiper.translate;\n      const newTranslate = Math.min(Math.max(translateValue, swiper.maxTranslate()), swiper.minTranslate());\n      swiper.setTranslate(newTranslate);\n      swiper.updateActiveIndex();\n      swiper.updateSlidesClasses();\n    }\n\n    let translated;\n\n    if (swiper.params.freeMode && swiper.params.freeMode.enabled) {\n      setTranslate();\n\n      if (swiper.params.autoHeight) {\n        swiper.updateAutoHeight();\n      }\n    } else {\n      if ((swiper.params.slidesPerView === 'auto' || swiper.params.slidesPerView > 1) && swiper.isEnd && !swiper.params.centeredSlides) {\n        translated = swiper.slideTo(swiper.slides.length - 1, 0, false, true);\n      } else {\n        translated = swiper.slideTo(swiper.activeIndex, 0, false, true);\n      }\n\n      if (!translated) {\n        setTranslate();\n      }\n    }\n\n    if (params.watchOverflow && snapGrid !== swiper.snapGrid) {\n      swiper.checkOverflow();\n    }\n\n    swiper.emit('update');\n  }\n\n  changeDirection(newDirection, needUpdate) {\n    if (needUpdate === void 0) {\n      needUpdate = true;\n    }\n\n    const swiper = this;\n    const currentDirection = swiper.params.direction;\n\n    if (!newDirection) {\n      // eslint-disable-next-line\n      newDirection = currentDirection === 'horizontal' ? 'vertical' : 'horizontal';\n    }\n\n    if (newDirection === currentDirection || newDirection !== 'horizontal' && newDirection !== 'vertical') {\n      return swiper;\n    }\n\n    swiper.$el.removeClass(`${swiper.params.containerModifierClass}${currentDirection}`).addClass(`${swiper.params.containerModifierClass}${newDirection}`);\n    swiper.emitContainerClasses();\n    swiper.params.direction = newDirection;\n    swiper.slides.each(slideEl => {\n      if (newDirection === 'vertical') {\n        slideEl.style.width = '';\n      } else {\n        slideEl.style.height = '';\n      }\n    });\n    swiper.emit('changeDirection');\n    if (needUpdate) swiper.update();\n    return swiper;\n  }\n\n  changeLanguageDirection(direction) {\n    const swiper = this;\n    if (swiper.rtl && direction === 'rtl' || !swiper.rtl && direction === 'ltr') return;\n    swiper.rtl = direction === 'rtl';\n    swiper.rtlTranslate = swiper.params.direction === 'horizontal' && swiper.rtl;\n\n    if (swiper.rtl) {\n      swiper.$el.addClass(`${swiper.params.containerModifierClass}rtl`);\n      swiper.el.dir = 'rtl';\n    } else {\n      swiper.$el.removeClass(`${swiper.params.containerModifierClass}rtl`);\n      swiper.el.dir = 'ltr';\n    }\n\n    swiper.update();\n  }\n\n  mount(el) {\n    const swiper = this;\n    if (swiper.mounted) return true; // Find el\n\n    const $el = $(el || swiper.params.el);\n    el = $el[0];\n\n    if (!el) {\n      return false;\n    }\n\n    el.swiper = swiper;\n\n    const getWrapperSelector = () => {\n      return `.${(swiper.params.wrapperClass || '').trim().split(' ').join('.')}`;\n    };\n\n    const getWrapper = () => {\n      if (el && el.shadowRoot && el.shadowRoot.querySelector) {\n        const res = $(el.shadowRoot.querySelector(getWrapperSelector())); // Children needs to return slot items\n\n        res.children = options => $el.children(options);\n\n        return res;\n      }\n\n      if (!$el.children) {\n        return $($el).children(getWrapperSelector());\n      }\n\n      return $el.children(getWrapperSelector());\n    }; // Find Wrapper\n\n\n    let $wrapperEl = getWrapper();\n\n    if ($wrapperEl.length === 0 && swiper.params.createElements) {\n      const document = getDocument();\n      const wrapper = document.createElement('div');\n      $wrapperEl = $(wrapper);\n      wrapper.className = swiper.params.wrapperClass;\n      $el.append(wrapper);\n      $el.children(`.${swiper.params.slideClass}`).each(slideEl => {\n        $wrapperEl.append(slideEl);\n      });\n    }\n\n    Object.assign(swiper, {\n      $el,\n      el,\n      $wrapperEl,\n      wrapperEl: $wrapperEl[0],\n      mounted: true,\n      // RTL\n      rtl: el.dir.toLowerCase() === 'rtl' || $el.css('direction') === 'rtl',\n      rtlTranslate: swiper.params.direction === 'horizontal' && (el.dir.toLowerCase() === 'rtl' || $el.css('direction') === 'rtl'),\n      wrongRTL: $wrapperEl.css('display') === '-webkit-box'\n    });\n    return true;\n  }\n\n  init(el) {\n    const swiper = this;\n    if (swiper.initialized) return swiper;\n    const mounted = swiper.mount(el);\n    if (mounted === false) return swiper;\n    swiper.emit('beforeInit'); // Set breakpoint\n\n    if (swiper.params.breakpoints) {\n      swiper.setBreakpoint();\n    } // Add Classes\n\n\n    swiper.addClasses(); // Create loop\n\n    if (swiper.params.loop) {\n      swiper.loopCreate();\n    } // Update size\n\n\n    swiper.updateSize(); // Update slides\n\n    swiper.updateSlides();\n\n    if (swiper.params.watchOverflow) {\n      swiper.checkOverflow();\n    } // Set Grab Cursor\n\n\n    if (swiper.params.grabCursor && swiper.enabled) {\n      swiper.setGrabCursor();\n    }\n\n    if (swiper.params.preloadImages) {\n      swiper.preloadImages();\n    } // Slide To Initial Slide\n\n\n    if (swiper.params.loop) {\n      swiper.slideTo(swiper.params.initialSlide + swiper.loopedSlides, 0, swiper.params.runCallbacksOnInit, false, true);\n    } else {\n      swiper.slideTo(swiper.params.initialSlide, 0, swiper.params.runCallbacksOnInit, false, true);\n    } // Attach events\n\n\n    swiper.attachEvents(); // Init Flag\n\n    swiper.initialized = true; // Emit\n\n    swiper.emit('init');\n    swiper.emit('afterInit');\n    return swiper;\n  }\n\n  destroy(deleteInstance, cleanStyles) {\n    if (deleteInstance === void 0) {\n      deleteInstance = true;\n    }\n\n    if (cleanStyles === void 0) {\n      cleanStyles = true;\n    }\n\n    const swiper = this;\n    const {\n      params,\n      $el,\n      $wrapperEl,\n      slides\n    } = swiper;\n\n    if (typeof swiper.params === 'undefined' || swiper.destroyed) {\n      return null;\n    }\n\n    swiper.emit('beforeDestroy'); // Init Flag\n\n    swiper.initialized = false; // Detach events\n\n    swiper.detachEvents(); // Destroy loop\n\n    if (params.loop) {\n      swiper.loopDestroy();\n    } // Cleanup styles\n\n\n    if (cleanStyles) {\n      swiper.removeClasses();\n      $el.removeAttr('style');\n      $wrapperEl.removeAttr('style');\n\n      if (slides && slides.length) {\n        slides.removeClass([params.slideVisibleClass, params.slideActiveClass, params.slideNextClass, params.slidePrevClass].join(' ')).removeAttr('style').removeAttr('data-swiper-slide-index');\n      }\n    }\n\n    swiper.emit('destroy'); // Detach emitter events\n\n    Object.keys(swiper.eventsListeners).forEach(eventName => {\n      swiper.off(eventName);\n    });\n\n    if (deleteInstance !== false) {\n      swiper.$el[0].swiper = null;\n      deleteProps(swiper);\n    }\n\n    swiper.destroyed = true;\n    return null;\n  }\n\n  static extendDefaults(newDefaults) {\n    extend(extendedDefaults, newDefaults);\n  }\n\n  static get extendedDefaults() {\n    return extendedDefaults;\n  }\n\n  static get defaults() {\n    return defaults;\n  }\n\n  static installModule(mod) {\n    if (!Swiper.prototype.__modules__) Swiper.prototype.__modules__ = [];\n    const modules = Swiper.prototype.__modules__;\n\n    if (typeof mod === 'function' && modules.indexOf(mod) < 0) {\n      modules.push(mod);\n    }\n  }\n\n  static use(module) {\n    if (Array.isArray(module)) {\n      module.forEach(m => Swiper.installModule(m));\n      return Swiper;\n    }\n\n    Swiper.installModule(module);\n    return Swiper;\n  }\n\n}\n\nObject.keys(prototypes).forEach(prototypeGroup => {\n  Object.keys(prototypes[prototypeGroup]).forEach(protoMethod => {\n    Swiper.prototype[protoMethod] = prototypes[prototypeGroup][protoMethod];\n  });\n});\nSwiper.use([Resize, Observer]);\nexport default Swiper;", "import Swiper from 'swiper'\n\nexport default () => ({\n  swiper: null,\n  init() {\n    this.swiper = new Swiper('.swiper', {\n      slidesPerView: 'auto',\n      rewind: true,\n      mousewheel: true,\n      scrollbar: true,\n      grabCursor: true,\n    })\n  },\n})\n", "/**\n * Returns the [year, month, day, hour, minute, seconds] tokens of the provided\n * `date` as it will be rendered in the `timeZone`.\n */\nexport default function tzTokenizeDate(date, timeZone) {\n  var dtf = getDateTimeFormat(timeZone)\n  return dtf.formatToParts ? partsOffset(dtf, date) : hackyOffset(dtf, date)\n}\n\nvar typeToPos = {\n  year: 0,\n  month: 1,\n  day: 2,\n  hour: 3,\n  minute: 4,\n  second: 5,\n}\n\nfunction partsOffset(dtf, date) {\n  var formatted = dtf.formatToParts(date)\n  var filled = []\n  for (var i = 0; i < formatted.length; i++) {\n    var pos = typeToPos[formatted[i].type]\n\n    if (pos >= 0) {\n      filled[pos] = parseInt(formatted[i].value, 10)\n    }\n  }\n  return filled\n}\n\nfunction hackyOffset(dtf, date) {\n  var formatted = dtf.format(date).replace(/\\u200E/g, '')\n  var parsed = /(\\d+)\\/(\\d+)\\/(\\d+),? (\\d+):(\\d+):(\\d+)/.exec(formatted)\n  // var [, fMonth, fDay, fYear, fHour, fMinute, fSecond] = parsed\n  // return [fYear, fMonth, fDay, fHour, fMinute, fSecond]\n  return [parsed[3], parsed[1], parsed[2], parsed[4], parsed[5], parsed[6]]\n}\n\n// Get a cached Intl.DateTimeFormat instance for the IANA `timeZone`. This can be used\n// to get deterministic local date/time output according to the `en-US` locale which\n// can be used to extract local time parts as necessary.\nvar dtfCache = {}\nfunction getDateTimeFormat(timeZone) {\n  if (!dtfCache[timeZone]) {\n    // New browsers use `hourCycle`, IE and Chrome <73 does not support it and uses `hour12`\n    var testDateFormatted = new Intl.DateTimeFormat('en-US', {\n      hour12: false,\n      timeZone: 'America/New_York',\n      year: 'numeric',\n      month: '2-digit',\n      day: '2-digit',\n      hour: '2-digit',\n      minute: '2-digit',\n      second: '2-digit',\n    }).format(new Date('2014-06-25T04:00:00.123Z'))\n    var hourCycleSupported =\n      testDateFormatted === '06/25/2014, 00:00:00' ||\n      testDateFormatted === '\u200E06\u200E/\u200E25\u200E/\u200E2014\u200E \u200E00\u200E:\u200E00\u200E:\u200E00'\n\n    dtfCache[timeZone] = hourCycleSupported\n      ? new Intl.DateTimeFormat('en-US', {\n          hour12: false,\n          timeZone: timeZone,\n          year: 'numeric',\n          month: '2-digit',\n          day: '2-digit',\n          hour: '2-digit',\n          minute: '2-digit',\n          second: '2-digit',\n        })\n      : new Intl.DateTimeFormat('en-US', {\n          hourCycle: 'h23',\n          timeZone: timeZone,\n          year: 'numeric',\n          month: '2-digit',\n          day: '2-digit',\n          hour: '2-digit',\n          minute: '2-digit',\n          second: '2-digit',\n        })\n  }\n  return dtfCache[timeZone]\n}\n", "import tzTokenizeDate from '../tzTokenizeDate/index.js'\n\nvar MILLISECONDS_IN_HOUR = 3600000\nvar MILLISECONDS_IN_MINUTE = 60000\n\nvar patterns = {\n  timezone: /([Z+-].*)$/,\n  timezoneZ: /^(Z)$/,\n  timezoneHH: /^([+-])(\\d{2})$/,\n  timezoneHHMM: /^([+-])(\\d{2}):?(\\d{2})$/,\n  timezoneIANA: /(UTC|(?:[a-zA-Z]+\\/[a-zA-Z_-]+(?:\\/[a-zA-Z_]+)?))$/,\n}\n\n// Parse various time zone offset formats to an offset in milliseconds\nexport default function tzParseTimezone(timezoneString, date, isUtcDate) {\n  var token\n  var absoluteOffset\n\n  // Z\n  token = patterns.timezoneZ.exec(timezoneString)\n  if (token) {\n    return 0\n  }\n\n  var hours\n\n  // \u00B1hh\n  token = patterns.timezoneHH.exec(timezoneString)\n  if (token) {\n    hours = parseInt(token[2], 10)\n\n    if (!validateTimezone(hours)) {\n      return NaN\n    }\n\n    absoluteOffset = hours * MILLISECONDS_IN_HOUR\n    return token[1] === '+' ? -absoluteOffset : absoluteOffset\n  }\n\n  // \u00B1hh:mm or \u00B1hhmm\n  token = patterns.timezoneHHMM.exec(timezoneString)\n  if (token) {\n    hours = parseInt(token[2], 10)\n    var minutes = parseInt(token[3], 10)\n\n    if (!validateTimezone(hours, minutes)) {\n      return NaN\n    }\n\n    absoluteOffset = hours * MILLISECONDS_IN_HOUR + minutes * MILLISECONDS_IN_MINUTE\n    return token[1] === '+' ? -absoluteOffset : absoluteOffset\n  }\n\n  // IANA time zone\n  token = patterns.timezoneIANA.exec(timezoneString)\n  if (token) {\n    date = new Date(date || Date.now())\n    var utcDate = isUtcDate ? date : toUtcDate(date)\n\n    var offset = calcOffset(utcDate, timezoneString)\n\n    var fixedOffset = isUtcDate ? offset : fixOffset(date, offset, timezoneString)\n\n    return -fixedOffset\n  }\n\n  return 0\n}\n\nfunction toUtcDate(date) {\n  return new Date(\n    Date.UTC(\n      date.getFullYear(),\n      date.getMonth(),\n      date.getDate(),\n      date.getHours(),\n      date.getMinutes(),\n      date.getSeconds(),\n      date.getMilliseconds()\n    )\n  )\n}\n\nfunction calcOffset(date, timezoneString) {\n  var tokens = tzTokenizeDate(date, timezoneString)\n\n  var asUTC = Date.UTC(tokens[0], tokens[1] - 1, tokens[2], tokens[3] % 24, tokens[4], tokens[5])\n\n  var asTS = date.getTime()\n  var over = asTS % 1000\n  asTS -= over >= 0 ? over : 1000 + over\n  return asUTC - asTS\n}\n\nfunction fixOffset(date, offset, timezoneString) {\n  var localTS = date.getTime()\n\n  // Our UTC time is just a guess because our offset is just a guess\n  var utcGuess = localTS - offset\n\n  // Test whether the zone matches the offset for this ts\n  var o2 = calcOffset(new Date(utcGuess), timezoneString)\n\n  // If so, offset didn't change and we're done\n  if (offset === o2) {\n    return offset\n  }\n\n  // If not, change the ts by the difference in the offset\n  utcGuess -= o2 - offset\n\n  // If that gives us the local time we want, we're done\n  var o3 = calcOffset(new Date(utcGuess), timezoneString)\n  if (o2 === o3) {\n    return o2\n  }\n\n  // If it's different, we're in a hole time. The offset has changed, but the we don't adjust the time\n  return Math.max(o2, o3)\n}\n\nfunction validateTimezone(hours, minutes) {\n  if (minutes != null && (minutes < 0 || minutes > 59)) {\n    return false\n  }\n\n  return true\n}\n", "import toInteger from 'date-fns/esm/_lib/toInteger/index.js'\nimport getTimezoneOffsetInMilliseconds from 'date-fns/esm/_lib/getTimezoneOffsetInMilliseconds/index.js'\nimport tzParseTimezone from '../_lib/tzParseTimezone'\n\nvar MILLISECONDS_IN_HOUR = 3600000\nvar MILLISECONDS_IN_MINUTE = 60000\nvar DEFAULT_ADDITIONAL_DIGITS = 2\n\nvar patterns = {\n  dateTimeDelimeter: /[T ]/,\n  plainTime: /:/,\n  timeZoneDelimeter: /[Z ]/i,\n\n  // year tokens\n  YY: /^(\\d{2})$/,\n  YYY: [\n    /^([+-]\\d{2})$/, // 0 additional digits\n    /^([+-]\\d{3})$/, // 1 additional digit\n    /^([+-]\\d{4})$/, // 2 additional digits\n  ],\n  YYYY: /^(\\d{4})/,\n  YYYYY: [\n    /^([+-]\\d{4})/, // 0 additional digits\n    /^([+-]\\d{5})/, // 1 additional digit\n    /^([+-]\\d{6})/, // 2 additional digits\n  ],\n\n  // date tokens\n  MM: /^-(\\d{2})$/,\n  DDD: /^-?(\\d{3})$/,\n  MMDD: /^-?(\\d{2})-?(\\d{2})$/,\n  Www: /^-?W(\\d{2})$/,\n  WwwD: /^-?W(\\d{2})-?(\\d{1})$/,\n\n  HH: /^(\\d{2}([.,]\\d*)?)$/,\n  HHMM: /^(\\d{2}):?(\\d{2}([.,]\\d*)?)$/,\n  HHMMSS: /^(\\d{2}):?(\\d{2}):?(\\d{2}([.,]\\d*)?)$/,\n\n  // timezone tokens (to identify the presence of a tz)\n  timezone: /([Z+-].*| UTC|(?:[a-zA-Z]+\\/[a-zA-Z_]+(?:\\/[a-zA-Z_]+)?))$/,\n}\n\n/**\n * @name toDate\n * @category Common Helpers\n * @summary Convert the given argument to an instance of Date.\n *\n * @description\n * Convert the given argument to an instance of Date.\n *\n * If the argument is an instance of Date, the function returns its clone.\n *\n * If the argument is a number, it is treated as a timestamp.\n *\n * If an argument is a string, the function tries to parse it.\n * Function accepts complete ISO 8601 formats as well as partial implementations.\n * ISO 8601: http://en.wikipedia.org/wiki/ISO_8601\n * If the function cannot parse the string or the values are invalid, it returns Invalid Date.\n *\n * If the argument is none of the above, the function returns Invalid Date.\n *\n * **Note**: *all* Date arguments passed to any *date-fns* function is processed by `toDate`.\n * All *date-fns* functions will throw `RangeError` if `options.additionalDigits` is not 0, 1, 2 or undefined.\n *\n * @param {Date|String|Number} argument - the value to convert\n * @param {OptionsWithTZ} [options] - the object with options. See [Options]{@link https://date-fns.org/docs/Options}\n * @param {0|1|2} [options.additionalDigits=2] - the additional number of digits in the extended year format\n * @param {String} [options.timeZone=''] - used to specify the IANA time zone offset of a date String.\n * @returns {Date} the parsed date in the local time zone\n * @throws {TypeError} 1 argument required\n * @throws {RangeError} `options.additionalDigits` must be 0, 1 or 2\n *\n * @example\n * // Convert string '2014-02-11T11:30:30' to date:\n * var result = toDate('2014-02-11T11:30:30')\n * //=> Tue Feb 11 2014 11:30:30\n *\n * @example\n * // Convert string '+02014101' to date,\n * // if the additional number of digits in the extended year format is 1:\n * var result = toDate('+02014101', {additionalDigits: 1})\n * //=> Fri Apr 11 2014 00:00:00\n */\nexport default function toDate(argument, dirtyOptions) {\n  if (arguments.length < 1) {\n    throw new TypeError('1 argument required, but only ' + arguments.length + ' present')\n  }\n\n  if (argument === null) {\n    return new Date(NaN)\n  }\n\n  var options = dirtyOptions || {}\n\n  var additionalDigits =\n    options.additionalDigits == null\n      ? DEFAULT_ADDITIONAL_DIGITS\n      : toInteger(options.additionalDigits)\n  if (additionalDigits !== 2 && additionalDigits !== 1 && additionalDigits !== 0) {\n    throw new RangeError('additionalDigits must be 0, 1 or 2')\n  }\n\n  // Clone the date\n  if (\n    argument instanceof Date ||\n    (typeof argument === 'object' && Object.prototype.toString.call(argument) === '[object Date]')\n  ) {\n    // Prevent the date to lose the milliseconds when passed to new Date() in IE10\n    return new Date(argument.getTime())\n  } else if (\n    typeof argument === 'number' ||\n    Object.prototype.toString.call(argument) === '[object Number]'\n  ) {\n    return new Date(argument)\n  } else if (\n    !(\n      typeof argument === 'string' || Object.prototype.toString.call(argument) === '[object String]'\n    )\n  ) {\n    return new Date(NaN)\n  }\n\n  var dateStrings = splitDateString(argument)\n\n  var parseYearResult = parseYear(dateStrings.date, additionalDigits)\n  var year = parseYearResult.year\n  var restDateString = parseYearResult.restDateString\n\n  var date = parseDate(restDateString, year)\n\n  if (isNaN(date)) {\n    return new Date(NaN)\n  }\n\n  if (date) {\n    var timestamp = date.getTime()\n    var time = 0\n    var offset\n\n    if (dateStrings.time) {\n      time = parseTime(dateStrings.time)\n\n      if (isNaN(time)) {\n        return new Date(NaN)\n      }\n    }\n\n    if (dateStrings.timezone || options.timeZone) {\n      offset = tzParseTimezone(dateStrings.timezone || options.timeZone, new Date(timestamp + time))\n      if (isNaN(offset)) {\n        return new Date(NaN)\n      }\n    } else {\n      // get offset accurate to hour in timezones that change offset\n      offset = getTimezoneOffsetInMilliseconds(new Date(timestamp + time))\n      offset = getTimezoneOffsetInMilliseconds(new Date(timestamp + time + offset))\n    }\n\n    return new Date(timestamp + time + offset)\n  } else {\n    return new Date(NaN)\n  }\n}\n\nfunction splitDateString(dateString) {\n  var dateStrings = {}\n  var array = dateString.split(patterns.dateTimeDelimeter)\n  var timeString\n\n  if (patterns.plainTime.test(array[0])) {\n    dateStrings.date = null\n    timeString = array[0]\n  } else {\n    dateStrings.date = array[0]\n    timeString = array[1]\n    dateStrings.timezone = array[2]\n    if (patterns.timeZoneDelimeter.test(dateStrings.date)) {\n      dateStrings.date = dateString.split(patterns.timeZoneDelimeter)[0]\n      timeString = dateString.substr(dateStrings.date.length, dateString.length)\n    }\n  }\n\n  if (timeString) {\n    var token = patterns.timezone.exec(timeString)\n    if (token) {\n      dateStrings.time = timeString.replace(token[1], '')\n      dateStrings.timezone = token[1]\n    } else {\n      dateStrings.time = timeString\n    }\n  }\n\n  return dateStrings\n}\n\nfunction parseYear(dateString, additionalDigits) {\n  var patternYYY = patterns.YYY[additionalDigits]\n  var patternYYYYY = patterns.YYYYY[additionalDigits]\n\n  var token\n\n  // YYYY or \u00B1YYYYY\n  token = patterns.YYYY.exec(dateString) || patternYYYYY.exec(dateString)\n  if (token) {\n    var yearString = token[1]\n    return {\n      year: parseInt(yearString, 10),\n      restDateString: dateString.slice(yearString.length),\n    }\n  }\n\n  // YY or \u00B1YYY\n  token = patterns.YY.exec(dateString) || patternYYY.exec(dateString)\n  if (token) {\n    var centuryString = token[1]\n    return {\n      year: parseInt(centuryString, 10) * 100,\n      restDateString: dateString.slice(centuryString.length),\n    }\n  }\n\n  // Invalid ISO-formatted year\n  return {\n    year: null,\n  }\n}\n\nfunction parseDate(dateString, year) {\n  // Invalid ISO-formatted year\n  if (year === null) {\n    return null\n  }\n\n  var token\n  var date\n  var month\n  var week\n\n  // YYYY\n  if (dateString.length === 0) {\n    date = new Date(0)\n    date.setUTCFullYear(year)\n    return date\n  }\n\n  // YYYY-MM\n  token = patterns.MM.exec(dateString)\n  if (token) {\n    date = new Date(0)\n    month = parseInt(token[1], 10) - 1\n\n    if (!validateDate(year, month)) {\n      return new Date(NaN)\n    }\n\n    date.setUTCFullYear(year, month)\n    return date\n  }\n\n  // YYYY-DDD or YYYYDDD\n  token = patterns.DDD.exec(dateString)\n  if (token) {\n    date = new Date(0)\n    var dayOfYear = parseInt(token[1], 10)\n\n    if (!validateDayOfYearDate(year, dayOfYear)) {\n      return new Date(NaN)\n    }\n\n    date.setUTCFullYear(year, 0, dayOfYear)\n    return date\n  }\n\n  // yyyy-MM-dd or YYYYMMDD\n  token = patterns.MMDD.exec(dateString)\n  if (token) {\n    date = new Date(0)\n    month = parseInt(token[1], 10) - 1\n    var day = parseInt(token[2], 10)\n\n    if (!validateDate(year, month, day)) {\n      return new Date(NaN)\n    }\n\n    date.setUTCFullYear(year, month, day)\n    return date\n  }\n\n  // YYYY-Www or YYYYWww\n  token = patterns.Www.exec(dateString)\n  if (token) {\n    week = parseInt(token[1], 10) - 1\n\n    if (!validateWeekDate(year, week)) {\n      return new Date(NaN)\n    }\n\n    return dayOfISOWeekYear(year, week)\n  }\n\n  // YYYY-Www-D or YYYYWwwD\n  token = patterns.WwwD.exec(dateString)\n  if (token) {\n    week = parseInt(token[1], 10) - 1\n    var dayOfWeek = parseInt(token[2], 10) - 1\n\n    if (!validateWeekDate(year, week, dayOfWeek)) {\n      return new Date(NaN)\n    }\n\n    return dayOfISOWeekYear(year, week, dayOfWeek)\n  }\n\n  // Invalid ISO-formatted date\n  return null\n}\n\nfunction parseTime(timeString) {\n  var token\n  var hours\n  var minutes\n\n  // hh\n  token = patterns.HH.exec(timeString)\n  if (token) {\n    hours = parseFloat(token[1].replace(',', '.'))\n\n    if (!validateTime(hours)) {\n      return NaN\n    }\n\n    return (hours % 24) * MILLISECONDS_IN_HOUR\n  }\n\n  // hh:mm or hhmm\n  token = patterns.HHMM.exec(timeString)\n  if (token) {\n    hours = parseInt(token[1], 10)\n    minutes = parseFloat(token[2].replace(',', '.'))\n\n    if (!validateTime(hours, minutes)) {\n      return NaN\n    }\n\n    return (hours % 24) * MILLISECONDS_IN_HOUR + minutes * MILLISECONDS_IN_MINUTE\n  }\n\n  // hh:mm:ss or hhmmss\n  token = patterns.HHMMSS.exec(timeString)\n  if (token) {\n    hours = parseInt(token[1], 10)\n    minutes = parseInt(token[2], 10)\n    var seconds = parseFloat(token[3].replace(',', '.'))\n\n    if (!validateTime(hours, minutes, seconds)) {\n      return NaN\n    }\n\n    return (hours % 24) * MILLISECONDS_IN_HOUR + minutes * MILLISECONDS_IN_MINUTE + seconds * 1000\n  }\n\n  // Invalid ISO-formatted time\n  return null\n}\n\nfunction dayOfISOWeekYear(isoWeekYear, week, day) {\n  week = week || 0\n  day = day || 0\n  var date = new Date(0)\n  date.setUTCFullYear(isoWeekYear, 0, 4)\n  var fourthOfJanuaryDay = date.getUTCDay() || 7\n  var diff = week * 7 + day + 1 - fourthOfJanuaryDay\n  date.setUTCDate(date.getUTCDate() + diff)\n  return date\n}\n\n// Validation functions\n\nvar DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]\nvar DAYS_IN_MONTH_LEAP_YEAR = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]\n\nfunction isLeapYearIndex(year) {\n  return year % 400 === 0 || (year % 4 === 0 && year % 100 !== 0)\n}\n\nfunction validateDate(year, month, date) {\n  if (month < 0 || month > 11) {\n    return false\n  }\n\n  if (date != null) {\n    if (date < 1) {\n      return false\n    }\n\n    var isLeapYear = isLeapYearIndex(year)\n    if (isLeapYear && date > DAYS_IN_MONTH_LEAP_YEAR[month]) {\n      return false\n    }\n    if (!isLeapYear && date > DAYS_IN_MONTH[month]) {\n      return false\n    }\n  }\n\n  return true\n}\n\nfunction validateDayOfYearDate(year, dayOfYear) {\n  if (dayOfYear < 1) {\n    return false\n  }\n\n  var isLeapYear = isLeapYearIndex(year)\n  if (isLeapYear && dayOfYear > 366) {\n    return false\n  }\n  if (!isLeapYear && dayOfYear > 365) {\n    return false\n  }\n\n  return true\n}\n\nfunction validateWeekDate(year, week, day) {\n  if (week < 0 || week > 52) {\n    return false\n  }\n\n  if (day != null && (day < 0 || day > 6)) {\n    return false\n  }\n\n  return true\n}\n\nfunction validateTime(hours, minutes, seconds) {\n  if (hours != null && (hours < 0 || hours >= 25)) {\n    return false\n  }\n\n  if (minutes != null && (minutes < 0 || minutes >= 60)) {\n    return false\n  }\n\n  if (seconds != null && (seconds < 0 || seconds >= 60)) {\n    return false\n  }\n\n  return true\n}\n", "import cloneObject from 'date-fns/esm/_lib/cloneObject'\nimport format from 'date-fns/esm/format'\nimport toDate from '../toDate'\n\n/**\n * @name zonedTimeToUtc\n * @category Time Zone Helpers\n * @summary Get the UTC date/time from a date representing local time in a given time zone\n *\n * @description\n * Returns a date instance with the UTC time of the provided date of which the values\n * represented the local time in the time zone specified. In other words, if the input\n * date represented local time in time time zone, the timestamp of the output date will\n * give the equivalent UTC of that local time regardless of the current system time zone.\n *\n * @param {Date|String|Number} date - the date with values representing the local time\n * @param {String} timeZone - the time zone of this local time, can be an offset or IANA time zone\n * @param {OptionsWithTZ} [options] - the object with options. See [Options]{@link https://date-fns.org/docs/Options}\n * @param {0|1|2} [options.additionalDigits=2] - passed to `toDate`. See [toDate]{@link https://date-fns.org/docs/toDate}\n * @returns {Date} the new date with the equivalent time in the time zone\n * @throws {TypeError} 2 arguments required\n * @throws {RangeError} `options.additionalDigits` must be 0, 1 or 2\n *\n * @example\n * // In June 10am in Los Angeles is 5pm UTC\n * const result = zonedTimeToUtc(new Date(2014, 5, 25, 10, 0, 0), 'America/Los_Angeles')\n * //=> 2014-06-25T17:00:00.000Z\n */\nexport default function zonedTimeToUtc(date, timeZone, options) {\n  if (date instanceof Date) {\n    date = format(date, \"yyyy-MM-dd'T'HH:mm:ss.SSS\")\n  }\n  var extendedOptions = cloneObject(options)\n  extendedOptions.timeZone = timeZone\n  return toDate(date, extendedOptions)\n}\n", "// canvas-confetti v1.6.0 built on 2022-10-24T21:26:41.619Z\nvar module = {};\n\n// source content\n(function main(global, module, isWorker, workerSize) {\n  var canUseWorker = !!(\n    global.Worker &&\n    global.Blob &&\n    global.Promise &&\n    global.OffscreenCanvas &&\n    global.OffscreenCanvasRenderingContext2D &&\n    global.HTMLCanvasElement &&\n    global.HTMLCanvasElement.prototype.transferControlToOffscreen &&\n    global.URL &&\n    global.URL.createObjectURL);\n\n  function noop() {}\n\n  // create a promise if it exists, otherwise, just\n  // call the function directly\n  function promise(func) {\n    var ModulePromise = module.exports.Promise;\n    var Prom = ModulePromise !== void 0 ? ModulePromise : global.Promise;\n\n    if (typeof Prom === 'function') {\n      return new Prom(func);\n    }\n\n    func(noop, noop);\n\n    return null;\n  }\n\n  var raf = (function () {\n    var TIME = Math.floor(1000 / 60);\n    var frame, cancel;\n    var frames = {};\n    var lastFrameTime = 0;\n\n    if (typeof requestAnimationFrame === 'function' && typeof cancelAnimationFrame === 'function') {\n      frame = function (cb) {\n        var id = Math.random();\n\n        frames[id] = requestAnimationFrame(function onFrame(time) {\n          if (lastFrameTime === time || lastFrameTime + TIME - 1 < time) {\n            lastFrameTime = time;\n            delete frames[id];\n\n            cb();\n          } else {\n            frames[id] = requestAnimationFrame(onFrame);\n          }\n        });\n\n        return id;\n      };\n      cancel = function (id) {\n        if (frames[id]) {\n          cancelAnimationFrame(frames[id]);\n        }\n      };\n    } else {\n      frame = function (cb) {\n        return setTimeout(cb, TIME);\n      };\n      cancel = function (timer) {\n        return clearTimeout(timer);\n      };\n    }\n\n    return { frame: frame, cancel: cancel };\n  }());\n\n  var getWorker = (function () {\n    var worker;\n    var prom;\n    var resolves = {};\n\n    function decorate(worker) {\n      function execute(options, callback) {\n        worker.postMessage({ options: options || {}, callback: callback });\n      }\n      worker.init = function initWorker(canvas) {\n        var offscreen = canvas.transferControlToOffscreen();\n        worker.postMessage({ canvas: offscreen }, [offscreen]);\n      };\n\n      worker.fire = function fireWorker(options, size, done) {\n        if (prom) {\n          execute(options, null);\n          return prom;\n        }\n\n        var id = Math.random().toString(36).slice(2);\n\n        prom = promise(function (resolve) {\n          function workerDone(msg) {\n            if (msg.data.callback !== id) {\n              return;\n            }\n\n            delete resolves[id];\n            worker.removeEventListener('message', workerDone);\n\n            prom = null;\n            done();\n            resolve();\n          }\n\n          worker.addEventListener('message', workerDone);\n          execute(options, id);\n\n          resolves[id] = workerDone.bind(null, { data: { callback: id }});\n        });\n\n        return prom;\n      };\n\n      worker.reset = function resetWorker() {\n        worker.postMessage({ reset: true });\n\n        for (var id in resolves) {\n          resolves[id]();\n          delete resolves[id];\n        }\n      };\n    }\n\n    return function () {\n      if (worker) {\n        return worker;\n      }\n\n      if (!isWorker && canUseWorker) {\n        var code = [\n          'var CONFETTI, SIZE = {}, module = {};',\n          '(' + main.toString() + ')(this, module, true, SIZE);',\n          'onmessage = function(msg) {',\n          '  if (msg.data.options) {',\n          '    CONFETTI(msg.data.options).then(function () {',\n          '      if (msg.data.callback) {',\n          '        postMessage({ callback: msg.data.callback });',\n          '      }',\n          '    });',\n          '  } else if (msg.data.reset) {',\n          '    CONFETTI && CONFETTI.reset();',\n          '  } else if (msg.data.resize) {',\n          '    SIZE.width = msg.data.resize.width;',\n          '    SIZE.height = msg.data.resize.height;',\n          '  } else if (msg.data.canvas) {',\n          '    SIZE.width = msg.data.canvas.width;',\n          '    SIZE.height = msg.data.canvas.height;',\n          '    CONFETTI = module.exports.create(msg.data.canvas);',\n          '  }',\n          '}',\n        ].join('\\n');\n        try {\n          worker = new Worker(URL.createObjectURL(new Blob([code])));\n        } catch (e) {\n          // eslint-disable-next-line no-console\n          typeof console !== undefined && typeof console.warn === 'function' ? console.warn('\uD83C\uDF8A Could not load worker', e) : null;\n\n          return null;\n        }\n\n        decorate(worker);\n      }\n\n      return worker;\n    };\n  })();\n\n  var defaults = {\n    particleCount: 50,\n    angle: 90,\n    spread: 45,\n    startVelocity: 45,\n    decay: 0.9,\n    gravity: 1,\n    drift: 0,\n    ticks: 200,\n    x: 0.5,\n    y: 0.5,\n    shapes: ['square', 'circle'],\n    zIndex: 100,\n    colors: [\n      '#26ccff',\n      '#a25afd',\n      '#ff5e7e',\n      '#88ff5a',\n      '#fcff42',\n      '#ffa62d',\n      '#ff36ff'\n    ],\n    // probably should be true, but back-compat\n    disableForReducedMotion: false,\n    scalar: 1\n  };\n\n  function convert(val, transform) {\n    return transform ? transform(val) : val;\n  }\n\n  function isOk(val) {\n    return !(val === null || val === undefined);\n  }\n\n  function prop(options, name, transform) {\n    return convert(\n      options && isOk(options[name]) ? options[name] : defaults[name],\n      transform\n    );\n  }\n\n  function onlyPositiveInt(number){\n    return number < 0 ? 0 : Math.floor(number);\n  }\n\n  function randomInt(min, max) {\n    // [min, max)\n    return Math.floor(Math.random() * (max - min)) + min;\n  }\n\n  function toDecimal(str) {\n    return parseInt(str, 16);\n  }\n\n  function colorsToRgb(colors) {\n    return colors.map(hexToRgb);\n  }\n\n  function hexToRgb(str) {\n    var val = String(str).replace(/[^0-9a-f]/gi, '');\n\n    if (val.length < 6) {\n        val = val[0]+val[0]+val[1]+val[1]+val[2]+val[2];\n    }\n\n    return {\n      r: toDecimal(val.substring(0,2)),\n      g: toDecimal(val.substring(2,4)),\n      b: toDecimal(val.substring(4,6))\n    };\n  }\n\n  function getOrigin(options) {\n    var origin = prop(options, 'origin', Object);\n    origin.x = prop(origin, 'x', Number);\n    origin.y = prop(origin, 'y', Number);\n\n    return origin;\n  }\n\n  function setCanvasWindowSize(canvas) {\n    canvas.width = document.documentElement.clientWidth;\n    canvas.height = document.documentElement.clientHeight;\n  }\n\n  function setCanvasRectSize(canvas) {\n    var rect = canvas.getBoundingClientRect();\n    canvas.width = rect.width;\n    canvas.height = rect.height;\n  }\n\n  function getCanvas(zIndex) {\n    var canvas = document.createElement('canvas');\n\n    canvas.style.position = 'fixed';\n    canvas.style.top = '0px';\n    canvas.style.left = '0px';\n    canvas.style.pointerEvents = 'none';\n    canvas.style.zIndex = zIndex;\n\n    return canvas;\n  }\n\n  function ellipse(context, x, y, radiusX, radiusY, rotation, startAngle, endAngle, antiClockwise) {\n    context.save();\n    context.translate(x, y);\n    context.rotate(rotation);\n    context.scale(radiusX, radiusY);\n    context.arc(0, 0, 1, startAngle, endAngle, antiClockwise);\n    context.restore();\n  }\n\n  function randomPhysics(opts) {\n    var radAngle = opts.angle * (Math.PI / 180);\n    var radSpread = opts.spread * (Math.PI / 180);\n\n    return {\n      x: opts.x,\n      y: opts.y,\n      wobble: Math.random() * 10,\n      wobbleSpeed: Math.min(0.11, Math.random() * 0.1 + 0.05),\n      velocity: (opts.startVelocity * 0.5) + (Math.random() * opts.startVelocity),\n      angle2D: -radAngle + ((0.5 * radSpread) - (Math.random() * radSpread)),\n      tiltAngle: (Math.random() * (0.75 - 0.25) + 0.25) * Math.PI,\n      color: opts.color,\n      shape: opts.shape,\n      tick: 0,\n      totalTicks: opts.ticks,\n      decay: opts.decay,\n      drift: opts.drift,\n      random: Math.random() + 2,\n      tiltSin: 0,\n      tiltCos: 0,\n      wobbleX: 0,\n      wobbleY: 0,\n      gravity: opts.gravity * 3,\n      ovalScalar: 0.6,\n      scalar: opts.scalar\n    };\n  }\n\n  function updateFetti(context, fetti) {\n    fetti.x += Math.cos(fetti.angle2D) * fetti.velocity + fetti.drift;\n    fetti.y += Math.sin(fetti.angle2D) * fetti.velocity + fetti.gravity;\n    fetti.wobble += fetti.wobbleSpeed;\n    fetti.velocity *= fetti.decay;\n    fetti.tiltAngle += 0.1;\n    fetti.tiltSin = Math.sin(fetti.tiltAngle);\n    fetti.tiltCos = Math.cos(fetti.tiltAngle);\n    fetti.random = Math.random() + 2;\n    fetti.wobbleX = fetti.x + ((10 * fetti.scalar) * Math.cos(fetti.wobble));\n    fetti.wobbleY = fetti.y + ((10 * fetti.scalar) * Math.sin(fetti.wobble));\n\n    var progress = (fetti.tick++) / fetti.totalTicks;\n\n    var x1 = fetti.x + (fetti.random * fetti.tiltCos);\n    var y1 = fetti.y + (fetti.random * fetti.tiltSin);\n    var x2 = fetti.wobbleX + (fetti.random * fetti.tiltCos);\n    var y2 = fetti.wobbleY + (fetti.random * fetti.tiltSin);\n\n    context.fillStyle = 'rgba(' + fetti.color.r + ', ' + fetti.color.g + ', ' + fetti.color.b + ', ' + (1 - progress) + ')';\n    context.beginPath();\n\n    if (fetti.shape === 'circle') {\n      context.ellipse ?\n        context.ellipse(fetti.x, fetti.y, Math.abs(x2 - x1) * fetti.ovalScalar, Math.abs(y2 - y1) * fetti.ovalScalar, Math.PI / 10 * fetti.wobble, 0, 2 * Math.PI) :\n        ellipse(context, fetti.x, fetti.y, Math.abs(x2 - x1) * fetti.ovalScalar, Math.abs(y2 - y1) * fetti.ovalScalar, Math.PI / 10 * fetti.wobble, 0, 2 * Math.PI);\n    } else if (fetti.shape === 'star') {\n      var rot = Math.PI / 2 * 3;\n      var innerRadius = 4 * fetti.scalar;\n      var outerRadius = 8 * fetti.scalar;\n      var x = fetti.x;\n      var y = fetti.y;\n      var spikes = 5;\n      var step = Math.PI / spikes;\n\n      while (spikes--) {\n        x = fetti.x + Math.cos(rot) * outerRadius;\n        y = fetti.y + Math.sin(rot) * outerRadius;\n        context.lineTo(x, y);\n        rot += step;\n\n        x = fetti.x + Math.cos(rot) * innerRadius;\n        y = fetti.y + Math.sin(rot) * innerRadius;\n        context.lineTo(x, y);\n        rot += step;\n      }\n    } else {\n      context.moveTo(Math.floor(fetti.x), Math.floor(fetti.y));\n      context.lineTo(Math.floor(fetti.wobbleX), Math.floor(y1));\n      context.lineTo(Math.floor(x2), Math.floor(y2));\n      context.lineTo(Math.floor(x1), Math.floor(fetti.wobbleY));\n    }\n\n    context.closePath();\n    context.fill();\n\n    return fetti.tick < fetti.totalTicks;\n  }\n\n  function animate(canvas, fettis, resizer, size, done) {\n    var animatingFettis = fettis.slice();\n    var context = canvas.getContext('2d');\n    var animationFrame;\n    var destroy;\n\n    var prom = promise(function (resolve) {\n      function onDone() {\n        animationFrame = destroy = null;\n\n        context.clearRect(0, 0, size.width, size.height);\n\n        done();\n        resolve();\n      }\n\n      function update() {\n        if (isWorker && !(size.width === workerSize.width && size.height === workerSize.height)) {\n          size.width = canvas.width = workerSize.width;\n          size.height = canvas.height = workerSize.height;\n        }\n\n        if (!size.width && !size.height) {\n          resizer(canvas);\n          size.width = canvas.width;\n          size.height = canvas.height;\n        }\n\n        context.clearRect(0, 0, size.width, size.height);\n\n        animatingFettis = animatingFettis.filter(function (fetti) {\n          return updateFetti(context, fetti);\n        });\n\n        if (animatingFettis.length) {\n          animationFrame = raf.frame(update);\n        } else {\n          onDone();\n        }\n      }\n\n      animationFrame = raf.frame(update);\n      destroy = onDone;\n    });\n\n    return {\n      addFettis: function (fettis) {\n        animatingFettis = animatingFettis.concat(fettis);\n\n        return prom;\n      },\n      canvas: canvas,\n      promise: prom,\n      reset: function () {\n        if (animationFrame) {\n          raf.cancel(animationFrame);\n        }\n\n        if (destroy) {\n          destroy();\n        }\n      }\n    };\n  }\n\n  function confettiCannon(canvas, globalOpts) {\n    var isLibCanvas = !canvas;\n    var allowResize = !!prop(globalOpts || {}, 'resize');\n    var globalDisableForReducedMotion = prop(globalOpts, 'disableForReducedMotion', Boolean);\n    var shouldUseWorker = canUseWorker && !!prop(globalOpts || {}, 'useWorker');\n    var worker = shouldUseWorker ? getWorker() : null;\n    var resizer = isLibCanvas ? setCanvasWindowSize : setCanvasRectSize;\n    var initialized = (canvas && worker) ? !!canvas.__confetti_initialized : false;\n    var preferLessMotion = typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion)').matches;\n    var animationObj;\n\n    function fireLocal(options, size, done) {\n      var particleCount = prop(options, 'particleCount', onlyPositiveInt);\n      var angle = prop(options, 'angle', Number);\n      var spread = prop(options, 'spread', Number);\n      var startVelocity = prop(options, 'startVelocity', Number);\n      var decay = prop(options, 'decay', Number);\n      var gravity = prop(options, 'gravity', Number);\n      var drift = prop(options, 'drift', Number);\n      var colors = prop(options, 'colors', colorsToRgb);\n      var ticks = prop(options, 'ticks', Number);\n      var shapes = prop(options, 'shapes');\n      var scalar = prop(options, 'scalar');\n      var origin = getOrigin(options);\n\n      var temp = particleCount;\n      var fettis = [];\n\n      var startX = canvas.width * origin.x;\n      var startY = canvas.height * origin.y;\n\n      while (temp--) {\n        fettis.push(\n          randomPhysics({\n            x: startX,\n            y: startY,\n            angle: angle,\n            spread: spread,\n            startVelocity: startVelocity,\n            color: colors[temp % colors.length],\n            shape: shapes[randomInt(0, shapes.length)],\n            ticks: ticks,\n            decay: decay,\n            gravity: gravity,\n            drift: drift,\n            scalar: scalar\n          })\n        );\n      }\n\n      // if we have a previous canvas already animating,\n      // add to it\n      if (animationObj) {\n        return animationObj.addFettis(fettis);\n      }\n\n      animationObj = animate(canvas, fettis, resizer, size , done);\n\n      return animationObj.promise;\n    }\n\n    function fire(options) {\n      var disableForReducedMotion = globalDisableForReducedMotion || prop(options, 'disableForReducedMotion', Boolean);\n      var zIndex = prop(options, 'zIndex', Number);\n\n      if (disableForReducedMotion && preferLessMotion) {\n        return promise(function (resolve) {\n          resolve();\n        });\n      }\n\n      if (isLibCanvas && animationObj) {\n        // use existing canvas from in-progress animation\n        canvas = animationObj.canvas;\n      } else if (isLibCanvas && !canvas) {\n        // create and initialize a new canvas\n        canvas = getCanvas(zIndex);\n        document.body.appendChild(canvas);\n      }\n\n      if (allowResize && !initialized) {\n        // initialize the size of a user-supplied canvas\n        resizer(canvas);\n      }\n\n      var size = {\n        width: canvas.width,\n        height: canvas.height\n      };\n\n      if (worker && !initialized) {\n        worker.init(canvas);\n      }\n\n      initialized = true;\n\n      if (worker) {\n        canvas.__confetti_initialized = true;\n      }\n\n      function onResize() {\n        if (worker) {\n          // TODO this really shouldn't be immediate, because it is expensive\n          var obj = {\n            getBoundingClientRect: function () {\n              if (!isLibCanvas) {\n                return canvas.getBoundingClientRect();\n              }\n            }\n          };\n\n          resizer(obj);\n\n          worker.postMessage({\n            resize: {\n              width: obj.width,\n              height: obj.height\n            }\n          });\n          return;\n        }\n\n        // don't actually query the size here, since this\n        // can execute frequently and rapidly\n        size.width = size.height = null;\n      }\n\n      function done() {\n        animationObj = null;\n\n        if (allowResize) {\n          global.removeEventListener('resize', onResize);\n        }\n\n        if (isLibCanvas && canvas) {\n          document.body.removeChild(canvas);\n          canvas = null;\n          initialized = false;\n        }\n      }\n\n      if (allowResize) {\n        global.addEventListener('resize', onResize, false);\n      }\n\n      if (worker) {\n        return worker.fire(options, size, done);\n      }\n\n      return fireLocal(options, size, done);\n    }\n\n    fire.reset = function () {\n      if (worker) {\n        worker.reset();\n      }\n\n      if (animationObj) {\n        animationObj.reset();\n      }\n    };\n\n    return fire;\n  }\n\n  // Make default export lazy to defer worker creation until called.\n  var defaultFire;\n  function getDefaultFire() {\n    if (!defaultFire) {\n      defaultFire = confettiCannon(null, { useWorker: true, resize: true });\n    }\n    return defaultFire;\n  }\n\n  module.exports = function() {\n    return getDefaultFire().apply(this, arguments);\n  };\n  module.exports.reset = function() {\n    getDefaultFire().reset();\n  };\n  module.exports.create = confettiCannon;\n}((function () {\n  if (typeof window !== 'undefined') {\n    return window;\n  }\n\n  if (typeof self !== 'undefined') {\n    return self;\n  }\n\n  return this || {};\n})(), module, false));\n\n// end source content\n\nexport default module.exports;\nexport var create = module.exports.create;\n", "import zonedTimeToUtc from 'date-fns-tz/zonedTimeToUtc'\nimport add from 'date-fns/add'\nimport differenceInDays from 'date-fns/differenceInDays'\nimport differenceInHours from 'date-fns/differenceInHours'\nimport differenceInMinutes from 'date-fns/differenceInMinutes'\nimport differenceInSeconds from 'date-fns/differenceInSeconds'\n\nimport confetti from 'canvas-confetti'\n\nexport const timer = ({ expireTime, addDays = 0, showDays = false }) => ({\n  time: new Date(),\n  init() {\n    setInterval(() => {\n      this.time = new Date()\n    }, 1000)\n  },\n  expiresIn() {\n    const parsedExpireTime = add(zonedTimeToUtc(expireTime, 'UTC'), {\n      days: addDays,\n    })\n\n    /* Never go below 0, and mod if provided */\n    const f = (val, mod) => Math.max(mod ? val % mod : val, 0)\n\n    const days = f(differenceInDays(parsedExpireTime, this.time))\n    const hours = f(differenceInHours(parsedExpireTime, this.time), 24)\n    const minutes = f(differenceInMinutes(parsedExpireTime, this.time), 60)\n    const seconds = f(differenceInSeconds(parsedExpireTime, this.time), 60)\n\n    return [showDays && `${days}d`, `${hours}h`, `${minutes}m`, `${seconds}s`]\n      .filter(Boolean)\n      .join(' ')\n  },\n})\n\nexport const toast = ({ message = 'Notification' }) => ({\n  open: false,\n  message,\n  openToast() {\n    this.open = true\n    setTimeout(() => {\n      this.open = false\n    }, 1000)\n  },\n})\n\nexport const sparks = ({ originElementId = 'sparks' } = {}) => ({\n  originElementId,\n  init() {\n    // console.log(`Sparks Initialized! - ${this.originElementId}`)\n  },\n  sparkOrigin() {\n    return document\n      .querySelector(`#${this.originElementId}`)\n      .getBoundingClientRect()\n  },\n  launch(e) {\n    if (e?.detail?.id !== this.originElementId) return\n\n    const { x, y } = this.sparkOrigin()\n    const confettiX = x / window.innerWidth\n    const confettiY = y / window.innerHeight\n\n    confetti({\n      particleCount: 20,\n      startVelocity: 10,\n      angle: 30,\n      spread: 40,\n      ticks: 50,\n      gravity: 0.5,\n      origin: { y: confettiY, x: confettiX },\n      colors: ['#bbf7d0', '#ffffff'],\n      scalar: 0.05,\n    })\n  },\n})\n\nexport const vh100 = () => ({\n  init() {\n    this.setVhUnits()\n  },\n  setVhUnits() {\n    let vh = window.innerHeight * 0.01\n    document.documentElement.style.setProperty('--vh', `${vh}px`)\n  },\n})\n", "// FLIP re-rank animation for the Dynamic Leaderboard (LOR-19, Phase 3).\n//\n// Ported from the demo prototype (loor-pitch-deck funding.js:215-283):\n// First/Last/Invert/Play. When LiveView re-sorts the <ol>, each row that moved\n// is animated from its previous position to its new one with a transform, so\n// the list appears to physically re-rank rather than jump.\n//\n//   * Rows are keyed by `data-user-id` so identity is tracked across re-sorts.\n//   * 380ms cubic-bezier(0.22, 1, 0.36, 1); new rows fade/slide in with a 60ms\n//     per-index stagger.\n//   * Honors `prefers-reduced-motion: reduce` \u2014 reorders instantly, no transform.\n//   * First paint never animates (we only have positions to animate *from* after\n//     the first measured render).\n//   * The board lives in a console pane toggled by Alpine `x-show` (display:none).\n//     Measuring a hidden element yields all-zero rects, which would fling every\n//     row across the viewport on the next re-rank \u2014 so we never measure/animate\n//     while hidden; we re-baseline when the pane is revealed (`lb:shown`).\n//   * Each play() supersedes any in-flight animation (tracked RAFs/timeouts are\n//     cancelled), and everything is cancelled on destroy \u2014 no orphaned timers\n//     writing transforms to detached or hidden rows.\n\nconst DURATION = 380\nconst EASING = 'cubic-bezier(0.22, 1, 0.36, 1)'\nconst STAGGER = 60\n\nconst prefersReducedMotion = () =>\n  window.matchMedia &&\n  window.matchMedia('(prefers-reduced-motion: reduce)').matches\n\nconst FlipList = {\n  mounted() {\n    this.firstPaint = true\n    this.needsRebaseline = false\n    this.rafs = new Set()\n    this.timers = new Set()\n\n    // When the leaderboard tab is revealed, adopt the now-laid-out positions as\n    // the baseline (no animation) so the next re-rank animates from real rects.\n    this.onShown = () => {\n      if (this.isVisible()) {\n        this.positions = this.measure()\n        this.needsRebaseline = false\n      }\n    }\n    window.addEventListener('lb:shown', this.onShown)\n\n    // Only seed a baseline if we're actually laid out; otherwise wait for reveal.\n    this.positions = this.isVisible() ? this.measure() : new Map()\n    if (!this.isVisible()) this.needsRebaseline = true\n    this.firstPaint = false\n  },\n\n  // LiveView has patched the DOM into its new order; animate from the old\n  // positions (FLIP) \u2014 but only if we're visible with a valid baseline.\n  updated() {\n    if (!this.isVisible()) {\n      // Patched while hidden: any positions we'd measure are zero-rects. Defer.\n      this.needsRebaseline = true\n      return\n    }\n    if (this.needsRebaseline) {\n      // Became visible (or first valid layout): adopt new layout, don't animate.\n      this.positions = this.measure()\n      this.needsRebaseline = false\n      return\n    }\n    this.play()\n  },\n\n  destroyed() {\n    window.removeEventListener('lb:shown', this.onShown)\n    this.cancelAll()\n  },\n\n  // --- internals --------------------------------------------------------\n\n  // display:none subtrees have a null offsetParent and no client rects; their\n  // getBoundingClientRect is all-zeros, which is poison for FLIP math.\n  isVisible() {\n    return this.el.offsetParent !== null && this.el.getClientRects().length > 0\n  },\n\n  rows() {\n    return Array.from(this.el.querySelectorAll('[data-user-id]'))\n  },\n\n  // Map of user-id -> bounding rect (the \"First\" / \"Last\" measurements).\n  measure() {\n    const map = new Map()\n    for (const row of this.rows()) {\n      map.set(row.dataset.userId, row.getBoundingClientRect())\n    }\n    return map\n  },\n\n  play() {\n    // A new re-rank supersedes any in-flight animation; otherwise overlapping\n    // FLIP passes measure each other's intermediate transforms and the rows jitter.\n    this.cancelAll()\n\n    const newPositions = this.measure()\n\n    if (prefersReducedMotion() || this.firstPaint) {\n      this.positions = newPositions\n      return\n    }\n\n    let newRowIndex = 0\n    for (const row of this.rows()) {\n      const id = row.dataset.userId\n      const prev = this.positions.get(id)\n      const next = newPositions.get(id)\n\n      if (!prev) {\n        // New entrant: fade + slide in, staggered by appearance order.\n        this.enter(row, newRowIndex++)\n        continue\n      }\n\n      const dy = prev.top - next.top\n      if (dy === 0) continue\n\n      // Invert: jump the row back to where it was, then play forward to 0.\n      row.style.transform = `translateY(${dy}px)`\n      row.style.transition = 'none'\n\n      this.raf(() => {\n        row.style.transform = ''\n        row.style.transition = `transform ${DURATION}ms ${EASING}`\n      })\n\n      this.clearAfter(row)\n    }\n\n    this.positions = newPositions\n  },\n\n  enter(row, index) {\n    row.style.opacity = '0'\n    row.style.transform = 'translateY(8px)'\n    row.style.transition = 'none'\n\n    this.raf(() => {\n      const delay = index * STAGGER\n      row.style.transition =\n        `opacity ${DURATION}ms ${EASING} ${delay}ms, transform ${DURATION}ms ${EASING} ${delay}ms`\n      row.style.opacity = '1'\n      row.style.transform = ''\n    })\n\n    this.clearAfter(row, index * STAGGER)\n  },\n\n  clearAfter(row, extra = 0) {\n    this.timer(() => {\n      row.style.transition = ''\n      row.style.transform = ''\n      row.style.opacity = ''\n    }, DURATION + extra + 20)\n  },\n\n  // Tracked rAF/timeout so a superseding play() or destroy() can cancel them.\n  raf(fn) {\n    const id = requestAnimationFrame(() => {\n      this.rafs.delete(id)\n      fn()\n    })\n    this.rafs.add(id)\n  },\n\n  timer(fn, ms) {\n    const id = window.setTimeout(() => {\n      this.timers.delete(id)\n      fn()\n    }, ms)\n    this.timers.add(id)\n  },\n\n  cancelAll() {\n    for (const id of this.rafs) cancelAnimationFrame(id)\n    this.rafs.clear()\n    for (const id of this.timers) clearTimeout(id)\n    this.timers.clear()\n    // Hard-reset any inline styles a cancelled animation left mid-flight, so a\n    // superseded/half-applied transform never becomes the next baseline.\n    for (const row of this.rows()) {\n      row.style.transition = ''\n      row.style.transform = ''\n      row.style.opacity = ''\n    }\n  },\n}\n\nexport default FlipList\n", "// Post-movie Producer Credits roll (LOR-20 part 2).\n//\n// Decision D4: build against the *current* Vimeo `@vimeo/player` now (the MUX\n// swap is decoupled), mirroring the demo's syncCredits cue mechanics\n// (funding.js:898-938) \u2014 but cue tiers/names come from server-rendered data,\n// NOT a hardcoded table.\n//\n// The watch page is a plain controller view (not a LiveView), and the player is\n// an Alpine component, so this ships as an Alpine factory (`creditsRoll`). It\n// does NOT construct its own Vimeo Player \u2014 `player.js` owns the single Player on\n// `#vimeo-player` and emits a plain DOM `movie:ended` event that this component\n// listens for. (A second `new Player()` on the same iframe would register a\n// duplicate, never-torn-down `window` message listener \u2014 a leak across nav.)\n//\n//   * The server-rendered list inside this element is the no-JS fallback and the\n//     initial render-time snapshot.\n//   * On `movie:ended`, fetch a *fresh* snapshot from `data-credits-url` so any\n//     mid-movie funding is reflected; both are point-in-time, so refund-safe.\n//     A cold leaderboard cache at page-render can't burn an empty roll anymore.\n//   * Names are written with `textContent` only (never innerHTML), so a credit\n//     name can't inject markup.\n//   * `prefers-reduced-motion: reduce` \u2192 static/paged roll (no scroll animation).\n//   * No funders \u2192 the roll is skipped entirely.\n\nconst prefersReducedMotion = () =>\n  window.matchMedia &&\n  window.matchMedia('(prefers-reduced-motion: reduce)').matches\n\nexport default () => ({\n  rolled: false,\n  embed: null,\n  onEnded: null,\n  onResumed: null,\n  autoHideTimer: null,\n\n  init() {\n    // No funders at render: nothing to roll. (The fresh fetch only ever adds\n    // funders, and a roll with zero groups is pointless, so this is a safe gate.)\n    if (this.readGroups().length === 0) return\n\n    this.embed = document.getElementById('vimeo-player')\n    if (!this.embed) return\n\n    // Consume the single Player's end signal; no second Player is created here.\n    this.onEnded = () => this.roll()\n    this.embed.addEventListener('movie:ended', this.onEnded)\n\n    // Scrubbing back or hitting play after the roll appears clears it, so the\n    // viewer is never trapped on the credits with the controls covered\n    // (player.js dispatches movie:resumed on seek/play).\n    this.onResumed = () => this.dismiss()\n    this.embed.addEventListener('movie:resumed', this.onResumed)\n  },\n\n  // Alpine calls destroy() on teardown \u2014 remove the listeners so navigating away\n  // and back doesn't stack handlers.\n  destroy() {\n    if (this.embed && this.onEnded) {\n      this.embed.removeEventListener('movie:ended', this.onEnded)\n    }\n    if (this.embed && this.onResumed) {\n      this.embed.removeEventListener('movie:resumed', this.onResumed)\n    }\n    if (this.autoHideTimer) clearTimeout(this.autoHideTimer)\n  },\n\n  // Hide the roll and hand the player back. Bound to the \"Back to video\" button\n  // and to movie:resumed. Safe to call when already hidden (a no-op).\n  dismiss() {\n    if (this.autoHideTimer) {\n      clearTimeout(this.autoHideTimer)\n      this.autoHideTimer = null\n    }\n    this.$el.classList.add('hidden')\n    this.$el.classList.remove('credits-visible', 'credits-rolling', 'credits-static')\n  },\n\n  readGroups() {\n    const raw = this.$el.dataset.credits\n    if (!raw) return []\n    try {\n      const parsed = JSON.parse(raw)\n      return Array.isArray(parsed) ? parsed : []\n    } catch {\n      return []\n    }\n  },\n\n  async roll() {\n    if (this.rolled) return\n    this.rolled = true\n\n    // Refresh to the end-of-playback board; fall back to the render-time markup\n    // already in the DOM if the fetch fails.\n    await this.refreshGroups()\n\n    this.$el.classList.remove('hidden')\n    this.$el.classList.add('credits-visible')\n\n    const reduced = prefersReducedMotion()\n    this.$el.classList.add(reduced ? 'credits-static' : 'credits-rolling')\n\n    // Clear the roll once it's done so the player and its controls come back on\n    // their own \u2014 no click needed. Animated: when the scroll finishes. Static\n    // (reduced motion, no animation to end on): after a readable beat.\n    const inner = this.$el.querySelector('.credits-roll-inner')\n    if (reduced || !inner) {\n      this.autoHideTimer = setTimeout(() => this.dismiss(), 12000)\n    } else {\n      inner.addEventListener('animationend', () => this.dismiss(), { once: true })\n    }\n  },\n\n  async refreshGroups() {\n    const url = this.$el.dataset.creditsUrl\n    if (!url) return\n\n    try {\n      const res = await fetch(url, { headers: { Accept: 'application/json' } })\n      if (!res.ok) return\n      const body = await res.json()\n      if (Array.isArray(body.credits) && body.credits.length > 0) {\n        this.renderGroups(body.credits)\n      }\n    } catch {\n      // Keep the server-rendered fallback already in the DOM.\n    }\n  },\n\n  // Rebuild the roll body from fresh data using textContent only \u2014 never\n  // innerHTML \u2014 so a credit name cannot inject markup.\n  renderGroups(groups) {\n    const inner = this.$el.querySelector('.credits-roll-inner')\n    if (!inner) return\n\n    // Preserve the heading (first child), replace the per-tier groups after it.\n    const heading = inner.firstElementChild\n    inner.replaceChildren()\n    if (heading) inner.appendChild(heading)\n\n    for (const group of groups) {\n      const wrap = document.createElement('div')\n      wrap.className = 'flex flex-col gap-1'\n\n      const title = document.createElement('p')\n      title.className =\n        'text-xs font-semibold tracking-widest uppercase text-loor-gold'\n      title.textContent = group.title\n      wrap.appendChild(title)\n\n      for (const name of group.names || []) {\n        const el = document.createElement('p')\n        el.className = 'text-xl credit-name'\n        el.style.fontSynthesis = 'none'\n        el.textContent = name\n        wrap.appendChild(el)\n      }\n\n      inner.appendChild(wrap)\n    }\n  },\n})\n", "// PROJECT X live seat preview.\n//\n// While a LOOT slider moves (dock allocation or buy-modal ladder), this hook\n// paints a projected CREDITS panel \u2014 the viewer's committed total plus the\n// slider amount inserted into the real rankings \u2014 into the #px-lb-preview\n// overlay covering the credits panel. The real panel (LiveView-rendered) is\n// never touched: the overlay sits on top, and hiding it on release reveals\n// ground truth again.\n//\n// Data comes from the #px-lb-data JSON island, which LiveView re-renders on\n// every {:rank_changed} broadcast, so previews always rank against live data.\n// Rows are built with DOM APIs (textContent) \u2014 display names are user input.\n\nconst RankPreview = {\n  mounted() {\n    this.active = false\n    this.lastAmount = 0\n\n    this.onPreview = (e) => {\n      this.lastAmount = (e.detail && e.detail.amount) || 0\n      this.active = true\n      this.paint()\n    }\n\n    this.onPreviewEnd = () => {\n      this.active = false\n      const overlay = this.overlay()\n      if (overlay) {\n        overlay.classList.remove('px-preview-active')\n        overlay.innerHTML = ''\n      }\n    }\n\n    window.addEventListener('px:preview', this.onPreview)\n    window.addEventListener('px:preview-end', this.onPreviewEnd)\n  },\n\n  // Island re-rendered (rank change) mid-drag: repaint the projection\n  // against the fresh data.\n  updated() {\n    if (this.active) this.paint()\n  },\n\n  destroyed() {\n    window.removeEventListener('px:preview', this.onPreview)\n    window.removeEventListener('px:preview-end', this.onPreviewEnd)\n  },\n\n  // --- internals ----------------------------------------------------------\n\n  overlay() {\n    return this.el.querySelector('#px-lb-preview')\n  },\n\n  data() {\n    const island = document.getElementById(this.el.dataset.island)\n    if (!island) return null\n    try {\n      return JSON.parse(island.textContent)\n    } catch (_e) {\n      return null\n    }\n  },\n\n  tierFor(data, rank) {\n    const exact = data.tiers_by_rank.find((t) => t.rank === rank)\n    return exact || data.tiers_by_rank[data.tiers_by_rank.length - 1] || null\n  },\n\n  // Projected entries: real rows minus the viewer, plus the viewer at\n  // committed + preview amount. Ties resolve in favor of existing funders\n  // (first-reached wins, matching Doubloon.Leaderboard.ahead?/2).\n  entries(data) {\n    const youTotal = (data.you.committed || 0) + this.lastAmount\n    const rows = data.rows.filter((r) => r.user_id !== data.you.user_id)\n\n    if (youTotal > 0) {\n      rows.push({\n        user_id: data.you.user_id || 'you',\n        display_name: data.you.display_name,\n        amount: youTotal,\n        you: true,\n      })\n    }\n\n    rows.sort((a, b) => b.amount - a.amount || (a.you ? 1 : 0) - (b.you ? 1 : 0))\n    return rows.slice(0, data.window)\n  },\n\n  // Same seat anatomy as Components.px_credits_panel, with the viewer's\n  // projected seat glowing.\n  paint() {\n    const overlay = this.overlay()\n    const data = this.data()\n    if (!overlay || !data) return\n\n    const entries = this.entries(data)\n\n    const panel = document.createElement('div')\n    panel.className = 'px-seats px-seats-preview'\n\n    for (let rank = 1; rank <= data.window; rank++) {\n      const entry = entries[rank - 1]\n      const tier = this.tierFor(data, rank)\n      const seat = document.createElement('div')\n      const seatCls =\n        rank === 1 ? 'px-seat-1' : rank === 2 ? 'px-seat-2' : rank === 3 ? 'px-seat-3' : 'px-seat-low'\n\n      const role = document.createElement('div')\n      role.className = 'px-seat-role'\n      role.textContent = (tier && tier.label) || `#${rank}`\n\n      const name = document.createElement('div')\n      const amt = document.createElement('div')\n\n      if (entry) {\n        seat.className = `px-seat ${seatCls}${entry.you ? ' px-seat-you px-seat-projected' : ''}`\n        name.className = 'px-seat-name'\n        name.textContent = entry.you ? `${entry.display_name} (you)` : entry.display_name\n        amt.className = 'px-seat-amt'\n        amt.append(lootMark(), ` ${entry.amount.toLocaleString()}`)\n      } else {\n        seat.className = `px-seat px-seat-open ${seatCls}`\n        name.className = 'px-seat-name px-seat-open-name'\n        name.textContent = '\u2014 open seat \u2014'\n        amt.className = 'px-seat-amt px-seat-claim'\n        amt.textContent = 'yours for the taking'\n      }\n\n      seat.append(role, name, amt)\n      panel.appendChild(seat)\n    }\n\n    // The viewer landed outside the window: pin their projected position.\n    const you = entries.find((e) => e.you)\n    if (!you) {\n      const youTotal = (data.you.committed || 0) + this.lastAmount\n      if (youTotal > 0) {\n        const pin = document.createElement('div')\n        pin.className = 'px-seat px-seat-pin px-seat-you px-seat-projected'\n        const role = document.createElement('div')\n        role.className = 'px-seat-role'\n        role.textContent = 'Special Thanks'\n        const name = document.createElement('div')\n        name.className = 'px-seat-name'\n        name.textContent = data.you.display_name\n        const amt = document.createElement('div')\n        amt.className = 'px-seat-amt'\n        amt.append(lootMark(), ` ${youTotal.toLocaleString()}`)\n        pin.append(role, name, amt)\n        panel.appendChild(pin)\n      }\n    }\n\n    overlay.innerHTML = ''\n    overlay.appendChild(panel)\n    overlay.classList.add('px-preview-active')\n  },\n}\n\n// The LOOT currency mark, inlined \u2014 mirrors the px_loot_mark component so\n// preview seats match the server-rendered ones (the icon kit's client-side\n// <i>-to-SVG swap doesn't run inside this overlay reliably).\nfunction lootMark() {\n  const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n  svg.setAttribute('class', 'px-loot-mark')\n  svg.setAttribute('viewBox', '0 0 403 512')\n  svg.setAttribute('aria-hidden', 'true')\n  svg.setAttribute('fill', 'currentColor')\n  const path = document.createElementNS('http://www.w3.org/2000/svg', 'path')\n  path.setAttribute('d', document.querySelector('.px-loot-mark path')?.getAttribute('d') || '')\n  svg.appendChild(path)\n  return svg\n}\n\nexport default RankPreview\n", "// PROJECT X funding clock (see ProjectGameStatus.ensure_funding_deadline!/1).\n//\n// The server owns the deadline (data-deadline, ISO8601); this hook only\n// renders the remaining time every second. When a pledge lands, LiveView\n// patches data-deadline, updated() fires, and the gained time flashes next\n// to the clock \u2014 the \"every pledge adds time\" mechanic made visible.\n\nconst PXCountdown = {\n  mounted() {\n    this.prevDeadline = null\n    this.start()\n  },\n\n  updated() {\n    this.start()\n  },\n\n  destroyed() {\n    clearInterval(this.timer)\n  },\n\n  start() {\n    clearInterval(this.timer)\n    const deadline = new Date(this.el.dataset.deadline)\n    if (isNaN(deadline)) return\n\n    if (this.prevDeadline && deadline > this.prevDeadline) {\n      this.flashGain(deadline - this.prevDeadline)\n    }\n    this.prevDeadline = deadline\n\n    const clock = this.el.querySelector('[data-clock]')\n    const render = () => {\n      const ms = deadline - Date.now()\n      clock.textContent = this.format(ms)\n      this.el.classList.toggle('px-countdown-low', ms > 0 && ms < 24 * 3600 * 1000)\n      this.el.classList.toggle('px-countdown-out', ms <= 0)\n      if (ms <= 0) clearInterval(this.timer)\n    }\n\n    render()\n    this.timer = setInterval(render, 1000)\n  },\n\n  format(ms) {\n    if (ms <= 0) return '00:00:00'\n    const total = Math.floor(ms / 1000)\n    const days = Math.floor(total / 86400)\n    const pad = (n) => String(n).padStart(2, '0')\n    const hms = `${pad(Math.floor((total % 86400) / 3600))}:${pad(Math.floor((total % 3600) / 60))}:${pad(total % 60)}`\n    return days > 0 ? `${days}d ${hms}` : hms\n  },\n\n  flashGain(gainedMs) {\n    const gain = this.el.querySelector('[data-gain]')\n    if (!gain) return\n    const mins = Math.round(gainedMs / 60000)\n    gain.textContent =\n      mins >= 60 ? `+${Math.floor(mins / 60)}h ${mins % 60}m` : `+${Math.max(mins, 1)}m`\n    gain.classList.remove('px-gain-flash')\n    void gain.offsetWidth\n    gain.classList.add('px-gain-flash')\n  },\n}\n\nexport default PXCountdown\n", "//---------------------------------------------------------------------\n//\n// QR Code Generator for JavaScript\n//\n// Copyright (c) 2009 Kazuhiko Arase\n//\n// URL: http://www.d-project.com/\n//\n// Licensed under the MIT license:\n//  http://www.opensource.org/licenses/mit-license.php\n//\n// The word 'QR Code' is registered trademark of\n// DENSO WAVE INCORPORATED\n//  http://www.denso-wave.com/qrcode/faqpatent-e.html\n//\n//---------------------------------------------------------------------\n\n//---------------------------------------------------------------------\n// qrcode\n//---------------------------------------------------------------------\n\n/**\n * qrcode\n * @param typeNumber 1 to 40\n * @param errorCorrectionLevel 'L','M','Q','H'\n */\nexport const qrcode = function(typeNumber, errorCorrectionLevel) {\n\n  const PAD0 = 0xEC;\n  const PAD1 = 0x11;\n\n  let _typeNumber = typeNumber;\n  const _errorCorrectionLevel = QRErrorCorrectionLevel[errorCorrectionLevel];\n  let _modules = null;\n  let _moduleCount = 0;\n  let _dataCache = null;\n  const _dataList = [];\n\n  const _this = {};\n\n  const makeImpl = function(test, maskPattern) {\n\n    _moduleCount = _typeNumber * 4 + 17;\n    _modules = function(moduleCount) {\n      const modules = new Array(moduleCount);\n      for (let row = 0; row < moduleCount; row += 1) {\n        modules[row] = new Array(moduleCount);\n        for (let col = 0; col < moduleCount; col += 1) {\n          modules[row][col] = null;\n        }\n      }\n      return modules;\n    }(_moduleCount);\n\n    setupPositionProbePattern(0, 0);\n    setupPositionProbePattern(_moduleCount - 7, 0);\n    setupPositionProbePattern(0, _moduleCount - 7);\n    setupPositionAdjustPattern();\n    setupTimingPattern();\n    setupTypeInfo(test, maskPattern);\n\n    if (_typeNumber >= 7) {\n      setupTypeNumber(test);\n    }\n\n    if (_dataCache == null) {\n      _dataCache = createData(_typeNumber, _errorCorrectionLevel, _dataList);\n    }\n\n    mapData(_dataCache, maskPattern);\n  };\n\n  const setupPositionProbePattern = function(row, col) {\n\n    for (let r = -1; r <= 7; r += 1) {\n\n      if (row + r <= -1 || _moduleCount <= row + r) continue;\n\n      for (let c = -1; c <= 7; c += 1) {\n\n        if (col + c <= -1 || _moduleCount <= col + c) continue;\n\n        if ( (0 <= r && r <= 6 && (c == 0 || c == 6) )\n            || (0 <= c && c <= 6 && (r == 0 || r == 6) )\n            || (2 <= r && r <= 4 && 2 <= c && c <= 4) ) {\n          _modules[row + r][col + c] = true;\n        } else {\n          _modules[row + r][col + c] = false;\n        }\n      }\n    }\n  };\n\n  const getBestMaskPattern = function() {\n\n    let minLostPoint = 0;\n    let pattern = 0;\n\n    for (let i = 0; i < 8; i += 1) {\n\n      makeImpl(true, i);\n\n      const lostPoint = QRUtil.getLostPoint(_this);\n\n      if (i == 0 || minLostPoint > lostPoint) {\n        minLostPoint = lostPoint;\n        pattern = i;\n      }\n    }\n\n    return pattern;\n  };\n\n  const setupTimingPattern = function() {\n\n    for (let r = 8; r < _moduleCount - 8; r += 1) {\n      if (_modules[r][6] != null) {\n        continue;\n      }\n      _modules[r][6] = (r % 2 == 0);\n    }\n\n    for (let c = 8; c < _moduleCount - 8; c += 1) {\n      if (_modules[6][c] != null) {\n        continue;\n      }\n      _modules[6][c] = (c % 2 == 0);\n    }\n  };\n\n  const setupPositionAdjustPattern = function() {\n\n    const pos = QRUtil.getPatternPosition(_typeNumber);\n\n    for (let i = 0; i < pos.length; i += 1) {\n\n      for (let j = 0; j < pos.length; j += 1) {\n\n        const row = pos[i];\n        const col = pos[j];\n\n        if (_modules[row][col] != null) {\n          continue;\n        }\n\n        for (let r = -2; r <= 2; r += 1) {\n\n          for (let c = -2; c <= 2; c += 1) {\n\n            if (r == -2 || r == 2 || c == -2 || c == 2\n                || (r == 0 && c == 0) ) {\n              _modules[row + r][col + c] = true;\n            } else {\n              _modules[row + r][col + c] = false;\n            }\n          }\n        }\n      }\n    }\n  };\n\n  const setupTypeNumber = function(test) {\n\n    const bits = QRUtil.getBCHTypeNumber(_typeNumber);\n\n    for (let i = 0; i < 18; i += 1) {\n      const mod = (!test && ( (bits >> i) & 1) == 1);\n      _modules[Math.floor(i / 3)][i % 3 + _moduleCount - 8 - 3] = mod;\n    }\n\n    for (let i = 0; i < 18; i += 1) {\n      const mod = (!test && ( (bits >> i) & 1) == 1);\n      _modules[i % 3 + _moduleCount - 8 - 3][Math.floor(i / 3)] = mod;\n    }\n  };\n\n  const setupTypeInfo = function(test, maskPattern) {\n\n    const data = (_errorCorrectionLevel << 3) | maskPattern;\n    const bits = QRUtil.getBCHTypeInfo(data);\n\n    // vertical\n    for (let i = 0; i < 15; i += 1) {\n\n      const mod = (!test && ( (bits >> i) & 1) == 1);\n\n      if (i < 6) {\n        _modules[i][8] = mod;\n      } else if (i < 8) {\n        _modules[i + 1][8] = mod;\n      } else {\n        _modules[_moduleCount - 15 + i][8] = mod;\n      }\n    }\n\n    // horizontal\n    for (let i = 0; i < 15; i += 1) {\n\n      const mod = (!test && ( (bits >> i) & 1) == 1);\n\n      if (i < 8) {\n        _modules[8][_moduleCount - i - 1] = mod;\n      } else if (i < 9) {\n        _modules[8][15 - i - 1 + 1] = mod;\n      } else {\n        _modules[8][15 - i - 1] = mod;\n      }\n    }\n\n    // fixed module\n    _modules[_moduleCount - 8][8] = (!test);\n  };\n\n  const mapData = function(data, maskPattern) {\n\n    let inc = -1;\n    let row = _moduleCount - 1;\n    let bitIndex = 7;\n    let byteIndex = 0;\n    const maskFunc = QRUtil.getMaskFunction(maskPattern);\n\n    for (let col = _moduleCount - 1; col > 0; col -= 2) {\n\n      if (col == 6) col -= 1;\n\n      while (true) {\n\n        for (let c = 0; c < 2; c += 1) {\n\n          if (_modules[row][col - c] == null) {\n\n            let dark = false;\n\n            if (byteIndex < data.length) {\n              dark = ( ( (data[byteIndex] >>> bitIndex) & 1) == 1);\n            }\n\n            const mask = maskFunc(row, col - c);\n\n            if (mask) {\n              dark = !dark;\n            }\n\n            _modules[row][col - c] = dark;\n            bitIndex -= 1;\n\n            if (bitIndex == -1) {\n              byteIndex += 1;\n              bitIndex = 7;\n            }\n          }\n        }\n\n        row += inc;\n\n        if (row < 0 || _moduleCount <= row) {\n          row -= inc;\n          inc = -inc;\n          break;\n        }\n      }\n    }\n  };\n\n  const createBytes = function(buffer, rsBlocks) {\n\n    let offset = 0;\n\n    let maxDcCount = 0;\n    let maxEcCount = 0;\n\n    const dcdata = new Array(rsBlocks.length);\n    const ecdata = new Array(rsBlocks.length);\n\n    for (let r = 0; r < rsBlocks.length; r += 1) {\n\n      const dcCount = rsBlocks[r].dataCount;\n      const ecCount = rsBlocks[r].totalCount - dcCount;\n\n      maxDcCount = Math.max(maxDcCount, dcCount);\n      maxEcCount = Math.max(maxEcCount, ecCount);\n\n      dcdata[r] = new Array(dcCount);\n\n      for (let i = 0; i < dcdata[r].length; i += 1) {\n        dcdata[r][i] = 0xff & buffer.getBuffer()[i + offset];\n      }\n      offset += dcCount;\n\n      const rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);\n      const rawPoly = qrPolynomial(dcdata[r], rsPoly.getLength() - 1);\n\n      const modPoly = rawPoly.mod(rsPoly);\n      ecdata[r] = new Array(rsPoly.getLength() - 1);\n      for (let i = 0; i < ecdata[r].length; i += 1) {\n        const modIndex = i + modPoly.getLength() - ecdata[r].length;\n        ecdata[r][i] = (modIndex >= 0)? modPoly.getAt(modIndex) : 0;\n      }\n    }\n\n    let totalCodeCount = 0;\n    for (let i = 0; i < rsBlocks.length; i += 1) {\n      totalCodeCount += rsBlocks[i].totalCount;\n    }\n\n    const data = new Array(totalCodeCount);\n    let index = 0;\n\n    for (let i = 0; i < maxDcCount; i += 1) {\n      for (let r = 0; r < rsBlocks.length; r += 1) {\n        if (i < dcdata[r].length) {\n          data[index] = dcdata[r][i];\n          index += 1;\n        }\n      }\n    }\n\n    for (let i = 0; i < maxEcCount; i += 1) {\n      for (let r = 0; r < rsBlocks.length; r += 1) {\n        if (i < ecdata[r].length) {\n          data[index] = ecdata[r][i];\n          index += 1;\n        }\n      }\n    }\n\n    return data;\n  };\n\n  const createData = function(typeNumber, errorCorrectionLevel, dataList) {\n\n    const rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectionLevel);\n\n    const buffer = qrBitBuffer();\n\n    for (let i = 0; i < dataList.length; i += 1) {\n      const data = dataList[i];\n      buffer.put(data.getMode(), 4);\n      buffer.put(data.getLength(), QRUtil.getLengthInBits(data.getMode(), typeNumber) );\n      data.write(buffer);\n    }\n\n    // calc num max data.\n    let totalDataCount = 0;\n    for (let i = 0; i < rsBlocks.length; i += 1) {\n      totalDataCount += rsBlocks[i].dataCount;\n    }\n\n    if (buffer.getLengthInBits() > totalDataCount * 8) {\n      throw 'code length overflow. ('\n        + buffer.getLengthInBits()\n        + '>'\n        + totalDataCount * 8\n        + ')';\n    }\n\n    // end code\n    if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) {\n      buffer.put(0, 4);\n    }\n\n    // padding\n    while (buffer.getLengthInBits() % 8 != 0) {\n      buffer.putBit(false);\n    }\n\n    // padding\n    while (true) {\n\n      if (buffer.getLengthInBits() >= totalDataCount * 8) {\n        break;\n      }\n      buffer.put(PAD0, 8);\n\n      if (buffer.getLengthInBits() >= totalDataCount * 8) {\n        break;\n      }\n      buffer.put(PAD1, 8);\n    }\n\n    return createBytes(buffer, rsBlocks);\n  };\n\n  _this.addData = function(data, mode) {\n\n    mode = mode || 'Byte';\n\n    let newData = null;\n\n    switch(mode) {\n    case 'Numeric' :\n      newData = qrNumber(data);\n      break;\n    case 'Alphanumeric' :\n      newData = qrAlphaNum(data);\n      break;\n    case 'Byte' :\n      newData = qr8BitByte(data);\n      break;\n    case 'Kanji' :\n      newData = qrKanji(data);\n      break;\n    default :\n      throw 'mode:' + mode;\n    }\n\n    _dataList.push(newData);\n    _dataCache = null;\n  };\n\n  _this.isDark = function(row, col) {\n    if (row < 0 || _moduleCount <= row || col < 0 || _moduleCount <= col) {\n      throw row + ',' + col;\n    }\n    return _modules[row][col];\n  };\n\n  _this.getModuleCount = function() {\n    return _moduleCount;\n  };\n\n  _this.make = function() {\n    if (_typeNumber < 1) {\n      let typeNumber = 1;\n\n      for (; typeNumber < 40; typeNumber++) {\n        const rsBlocks = QRRSBlock.getRSBlocks(typeNumber, _errorCorrectionLevel);\n        const buffer = qrBitBuffer();\n\n        for (let i = 0; i < _dataList.length; i++) {\n          const data = _dataList[i];\n          buffer.put(data.getMode(), 4);\n          buffer.put(data.getLength(), QRUtil.getLengthInBits(data.getMode(), typeNumber) );\n          data.write(buffer);\n        }\n\n        let totalDataCount = 0;\n        for (let i = 0; i < rsBlocks.length; i++) {\n          totalDataCount += rsBlocks[i].dataCount;\n        }\n\n        if (buffer.getLengthInBits() <= totalDataCount * 8) {\n          break;\n        }\n      }\n\n      _typeNumber = typeNumber;\n    }\n\n    makeImpl(false, getBestMaskPattern() );\n  };\n\n  _this.createTableTag = function(cellSize, margin) {\n\n    cellSize = cellSize || 2;\n    margin = (typeof margin == 'undefined')? cellSize * 4 : margin;\n\n    let qrHtml = '';\n\n    qrHtml += '<table style=\"';\n    qrHtml += ' border-width: 0px; border-style: none;';\n    qrHtml += ' border-collapse: collapse;';\n    qrHtml += ' padding: 0px; margin: ' + margin + 'px;';\n    qrHtml += '\">';\n    qrHtml += '<tbody>';\n\n    for (let r = 0; r < _this.getModuleCount(); r += 1) {\n\n      qrHtml += '<tr>';\n\n      for (let c = 0; c < _this.getModuleCount(); c += 1) {\n        qrHtml += '<td style=\"';\n        qrHtml += ' border-width: 0px; border-style: none;';\n        qrHtml += ' border-collapse: collapse;';\n        qrHtml += ' padding: 0px; margin: 0px;';\n        qrHtml += ' width: ' + cellSize + 'px;';\n        qrHtml += ' height: ' + cellSize + 'px;';\n        qrHtml += ' background-color: ';\n        qrHtml += _this.isDark(r, c)? '#000000' : '#ffffff';\n        qrHtml += ';';\n        qrHtml += '\"/>';\n      }\n\n      qrHtml += '</tr>';\n    }\n\n    qrHtml += '</tbody>';\n    qrHtml += '</table>';\n\n    return qrHtml;\n  };\n\n  _this.createSvgTag = function(cellSize, margin, alt, title) {\n\n    let opts = {};\n    if (typeof arguments[0] == 'object') {\n      // Called by options.\n      opts = arguments[0];\n      // overwrite cellSize and margin.\n      cellSize = opts.cellSize;\n      margin = opts.margin;\n      alt = opts.alt;\n      title = opts.title;\n    }\n\n    cellSize = cellSize || 2;\n    margin = (typeof margin == 'undefined')? cellSize * 4 : margin;\n\n    // Compose alt property surrogate\n    alt = (typeof alt === 'string') ? {text: alt} : alt || {};\n    alt.text = alt.text || null;\n    alt.id = (alt.text) ? alt.id || 'qrcode-description' : null;\n\n    // Compose title property surrogate\n    title = (typeof title === 'string') ? {text: title} : title || {};\n    title.text = title.text || null;\n    title.id = (title.text) ? title.id || 'qrcode-title' : null;\n\n    const size = _this.getModuleCount() * cellSize + margin * 2;\n    let c, mc, r, mr, qrSvg='', rect;\n\n    rect = 'l' + cellSize + ',0 0,' + cellSize +\n      ' -' + cellSize + ',0 0,-' + cellSize + 'z ';\n\n    qrSvg += '<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"';\n    qrSvg += !opts.scalable ? ' width=\"' + size + 'px\" height=\"' + size + 'px\"' : '';\n    qrSvg += ' viewBox=\"0 0 ' + size + ' ' + size + '\" ';\n    qrSvg += ' preserveAspectRatio=\"xMinYMin meet\"';\n    qrSvg += (title.text || alt.text) ? ' role=\"img\" aria-labelledby=\"' +\n        escapeXml([title.id, alt.id].join(' ').trim() ) + '\"' : '';\n    qrSvg += '>';\n    qrSvg += (title.text) ? '<title id=\"' + escapeXml(title.id) + '\">' +\n        escapeXml(title.text) + '</title>' : '';\n    qrSvg += (alt.text) ? '<description id=\"' + escapeXml(alt.id) + '\">' +\n        escapeXml(alt.text) + '</description>' : '';\n    qrSvg += '<rect width=\"100%\" height=\"100%\" fill=\"white\" cx=\"0\" cy=\"0\"/>';\n    qrSvg += '<path d=\"';\n\n    for (r = 0; r < _this.getModuleCount(); r += 1) {\n      mr = r * cellSize + margin;\n      for (c = 0; c < _this.getModuleCount(); c += 1) {\n        if (_this.isDark(r, c) ) {\n          mc = c*cellSize+margin;\n          qrSvg += 'M' + mc + ',' + mr + rect;\n        }\n      }\n    }\n\n    qrSvg += '\" stroke=\"transparent\" fill=\"black\"/>';\n    qrSvg += '</svg>';\n\n    return qrSvg;\n  };\n\n  _this.createDataURL = function(cellSize, margin) {\n\n    cellSize = cellSize || 2;\n    margin = (typeof margin == 'undefined')? cellSize * 4 : margin;\n\n    const size = _this.getModuleCount() * cellSize + margin * 2;\n    const min = margin;\n    const max = size - margin;\n\n    return createDataURL(size, size, function(x, y) {\n      if (min <= x && x < max && min <= y && y < max) {\n        const c = Math.floor( (x - min) / cellSize);\n        const r = Math.floor( (y - min) / cellSize);\n        return _this.isDark(r, c)? 0 : 1;\n      } else {\n        return 1;\n      }\n    } );\n  };\n\n  _this.createImgTag = function(cellSize, margin, alt) {\n\n    cellSize = cellSize || 2;\n    margin = (typeof margin == 'undefined')? cellSize * 4 : margin;\n\n    const size = _this.getModuleCount() * cellSize + margin * 2;\n\n    let img = '';\n    img += '<img';\n    img += '\\u0020src=\"';\n    img += _this.createDataURL(cellSize, margin);\n    img += '\"';\n    img += '\\u0020width=\"';\n    img += size;\n    img += '\"';\n    img += '\\u0020height=\"';\n    img += size;\n    img += '\"';\n    if (alt) {\n      img += '\\u0020alt=\"';\n      img += escapeXml(alt);\n      img += '\"';\n    }\n    img += '/>';\n\n    return img;\n  };\n\n  const escapeXml = function(s) {\n    let escaped = '';\n    for (let i = 0; i < s.length; i += 1) {\n      const c = s.charAt(i);\n      switch(c) {\n      case '<': escaped += '&lt;'; break;\n      case '>': escaped += '&gt;'; break;\n      case '&': escaped += '&amp;'; break;\n      case '\"': escaped += '&quot;'; break;\n      default : escaped += c; break;\n      }\n    }\n    return escaped;\n  };\n\n  const _createHalfASCII = function(margin) {\n    const cellSize = 1;\n    margin = (typeof margin == 'undefined')? cellSize * 2 : margin;\n\n    const size = _this.getModuleCount() * cellSize + margin * 2;\n    const min = margin;\n    const max = size - margin;\n\n    let y, x, r1, r2, p;\n\n    const blocks = {\n      '\u2588\u2588': '\u2588',\n      '\u2588 ': '\u2580',\n      ' \u2588': '\u2584',\n      '  ': ' '\n    };\n\n    const blocksLastLineNoMargin = {\n      '\u2588\u2588': '\u2580',\n      '\u2588 ': '\u2580',\n      ' \u2588': ' ',\n      '  ': ' '\n    };\n\n    let ascii = '';\n    for (y = 0; y < size; y += 2) {\n      r1 = Math.floor((y - min) / cellSize);\n      r2 = Math.floor((y + 1 - min) / cellSize);\n      for (x = 0; x < size; x += 1) {\n        p = '\u2588';\n\n        if (min <= x && x < max && min <= y && y < max && _this.isDark(r1, Math.floor((x - min) / cellSize))) {\n          p = ' ';\n        }\n\n        if (min <= x && x < max && min <= y+1 && y+1 < max && _this.isDark(r2, Math.floor((x - min) / cellSize))) {\n          p += ' ';\n        }\n        else {\n          p += '\u2588';\n        }\n\n        // Output 2 characters per pixel, to create full square. 1 character per pixels gives only half width of square.\n        ascii += (margin < 1 && y+1 >= max) ? blocksLastLineNoMargin[p] : blocks[p];\n      }\n\n      ascii += '\\n';\n    }\n\n    if (size % 2 && margin > 0) {\n      return ascii.substring(0, ascii.length - size - 1) + Array(size+1).join('\u2580');\n    }\n\n    return ascii.substring(0, ascii.length-1);\n  };\n\n  _this.createASCII = function(cellSize, margin) {\n    cellSize = cellSize || 1;\n\n    if (cellSize < 2) {\n      return _createHalfASCII(margin);\n    }\n\n    cellSize -= 1;\n    margin = (typeof margin == 'undefined')? cellSize * 2 : margin;\n\n    const size = _this.getModuleCount() * cellSize + margin * 2;\n    const min = margin;\n    const max = size - margin;\n\n    let y, x, r, p;\n\n    const white = Array(cellSize+1).join('\u2588\u2588');\n    const black = Array(cellSize+1).join('  ');\n\n    let ascii = '';\n    let line = '';\n    for (y = 0; y < size; y += 1) {\n      r = Math.floor( (y - min) / cellSize);\n      line = '';\n      for (x = 0; x < size; x += 1) {\n        p = 1;\n\n        if (min <= x && x < max && min <= y && y < max && _this.isDark(r, Math.floor((x - min) / cellSize))) {\n          p = 0;\n        }\n\n        // Output 2 characters per pixel, to create full square. 1 character per pixels gives only half width of square.\n        line += p ? white : black;\n      }\n\n      for (r = 0; r < cellSize; r += 1) {\n        ascii += line + '\\n';\n      }\n    }\n\n    return ascii.substring(0, ascii.length-1);\n  };\n\n  _this.renderTo2dContext = function(context, cellSize) {\n    cellSize = cellSize || 2;\n    const length = _this.getModuleCount();\n    for (let row = 0; row < length; row++) {\n      for (let col = 0; col < length; col++) {\n        context.fillStyle = _this.isDark(row, col) ? 'black' : 'white';\n        context.fillRect(col * cellSize, row * cellSize, cellSize, cellSize);\n      }\n    }\n  }\n\n  return _this;\n};\n\n//---------------------------------------------------------------------\n// qrcode.stringToBytes\n//---------------------------------------------------------------------\n\nqrcode.stringToBytes = function(s) {\n  const bytes = [];\n  for (let i = 0; i < s.length; i += 1) {\n    const c = s.charCodeAt(i);\n    bytes.push(c & 0xff);\n  }\n  return bytes;\n};\n\n//---------------------------------------------------------------------\n// qrcode.createStringToBytes\n//---------------------------------------------------------------------\n\n/**\n * @param unicodeData base64 string of byte array.\n * [16bit Unicode],[16bit Bytes], ...\n * @param numChars\n */\nqrcode.createStringToBytes = function(unicodeData, numChars) {\n\n  // create conversion map.\n\n  const unicodeMap = function() {\n\n    const bin = base64DecodeInputStream(unicodeData);\n    const read = function() {\n      const b = bin.read();\n      if (b == -1) throw 'eof';\n      return b;\n    };\n\n    let count = 0;\n    const unicodeMap = {};\n    while (true) {\n      const b0 = bin.read();\n      if (b0 == -1) break;\n      const b1 = read();\n      const b2 = read();\n      const b3 = read();\n      const k = String.fromCharCode( (b0 << 8) | b1);\n      const v = (b2 << 8) | b3;\n      unicodeMap[k] = v;\n      count += 1;\n    }\n    if (count != numChars) {\n      throw count + ' != ' + numChars;\n    }\n\n    return unicodeMap;\n  }();\n\n  const unknownChar = '?'.charCodeAt(0);\n\n  return function(s) {\n    const bytes = [];\n    for (let i = 0; i < s.length; i += 1) {\n      const c = s.charCodeAt(i);\n      if (c < 128) {\n        bytes.push(c);\n      } else {\n        const b = unicodeMap[s.charAt(i)];\n        if (typeof b == 'number') {\n          if ( (b & 0xff) == b) {\n            // 1byte\n            bytes.push(b);\n          } else {\n            // 2bytes\n            bytes.push(b >>> 8);\n            bytes.push(b & 0xff);\n          }\n        } else {\n          bytes.push(unknownChar);\n        }\n      }\n    }\n    return bytes;\n  };\n};\n\n//---------------------------------------------------------------------\n// QRMode\n//---------------------------------------------------------------------\n\nconst QRMode = {\n  MODE_NUMBER :    1 << 0,\n  MODE_ALPHA_NUM : 1 << 1,\n  MODE_8BIT_BYTE : 1 << 2,\n  MODE_KANJI :     1 << 3\n};\n\n//---------------------------------------------------------------------\n// QRErrorCorrectionLevel\n//---------------------------------------------------------------------\n\nconst QRErrorCorrectionLevel = {\n  L : 1,\n  M : 0,\n  Q : 3,\n  H : 2\n};\n\n//---------------------------------------------------------------------\n// QRMaskPattern\n//---------------------------------------------------------------------\n\nconst QRMaskPattern = {\n  PATTERN000 : 0,\n  PATTERN001 : 1,\n  PATTERN010 : 2,\n  PATTERN011 : 3,\n  PATTERN100 : 4,\n  PATTERN101 : 5,\n  PATTERN110 : 6,\n  PATTERN111 : 7\n};\n\n//---------------------------------------------------------------------\n// QRUtil\n//---------------------------------------------------------------------\n\nconst QRUtil = function() {\n\n  const PATTERN_POSITION_TABLE = [\n    [],\n    [6, 18],\n    [6, 22],\n    [6, 26],\n    [6, 30],\n    [6, 34],\n    [6, 22, 38],\n    [6, 24, 42],\n    [6, 26, 46],\n    [6, 28, 50],\n    [6, 30, 54],\n    [6, 32, 58],\n    [6, 34, 62],\n    [6, 26, 46, 66],\n    [6, 26, 48, 70],\n    [6, 26, 50, 74],\n    [6, 30, 54, 78],\n    [6, 30, 56, 82],\n    [6, 30, 58, 86],\n    [6, 34, 62, 90],\n    [6, 28, 50, 72, 94],\n    [6, 26, 50, 74, 98],\n    [6, 30, 54, 78, 102],\n    [6, 28, 54, 80, 106],\n    [6, 32, 58, 84, 110],\n    [6, 30, 58, 86, 114],\n    [6, 34, 62, 90, 118],\n    [6, 26, 50, 74, 98, 122],\n    [6, 30, 54, 78, 102, 126],\n    [6, 26, 52, 78, 104, 130],\n    [6, 30, 56, 82, 108, 134],\n    [6, 34, 60, 86, 112, 138],\n    [6, 30, 58, 86, 114, 142],\n    [6, 34, 62, 90, 118, 146],\n    [6, 30, 54, 78, 102, 126, 150],\n    [6, 24, 50, 76, 102, 128, 154],\n    [6, 28, 54, 80, 106, 132, 158],\n    [6, 32, 58, 84, 110, 136, 162],\n    [6, 26, 54, 82, 110, 138, 166],\n    [6, 30, 58, 86, 114, 142, 170]\n  ];\n  const G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0);\n  const G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0);\n  const G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1);\n\n  const _this = {};\n\n  const getBCHDigit = function(data) {\n    let digit = 0;\n    while (data != 0) {\n      digit += 1;\n      data >>>= 1;\n    }\n    return digit;\n  };\n\n  _this.getBCHTypeInfo = function(data) {\n    let d = data << 10;\n    while (getBCHDigit(d) - getBCHDigit(G15) >= 0) {\n      d ^= (G15 << (getBCHDigit(d) - getBCHDigit(G15) ) );\n    }\n    return ( (data << 10) | d) ^ G15_MASK;\n  };\n\n  _this.getBCHTypeNumber = function(data) {\n    let d = data << 12;\n    while (getBCHDigit(d) - getBCHDigit(G18) >= 0) {\n      d ^= (G18 << (getBCHDigit(d) - getBCHDigit(G18) ) );\n    }\n    return (data << 12) | d;\n  };\n\n  _this.getPatternPosition = function(typeNumber) {\n    return PATTERN_POSITION_TABLE[typeNumber - 1];\n  };\n\n  _this.getMaskFunction = function(maskPattern) {\n\n    switch (maskPattern) {\n\n    case QRMaskPattern.PATTERN000 :\n      return function(i, j) { return (i + j) % 2 == 0; };\n    case QRMaskPattern.PATTERN001 :\n      return function(i, j) { return i % 2 == 0; };\n    case QRMaskPattern.PATTERN010 :\n      return function(i, j) { return j % 3 == 0; };\n    case QRMaskPattern.PATTERN011 :\n      return function(i, j) { return (i + j) % 3 == 0; };\n    case QRMaskPattern.PATTERN100 :\n      return function(i, j) { return (Math.floor(i / 2) + Math.floor(j / 3) ) % 2 == 0; };\n    case QRMaskPattern.PATTERN101 :\n      return function(i, j) { return (i * j) % 2 + (i * j) % 3 == 0; };\n    case QRMaskPattern.PATTERN110 :\n      return function(i, j) { return ( (i * j) % 2 + (i * j) % 3) % 2 == 0; };\n    case QRMaskPattern.PATTERN111 :\n      return function(i, j) { return ( (i * j) % 3 + (i + j) % 2) % 2 == 0; };\n\n    default :\n      throw 'bad maskPattern:' + maskPattern;\n    }\n  };\n\n  _this.getErrorCorrectPolynomial = function(errorCorrectLength) {\n    let a = qrPolynomial([1], 0);\n    for (let i = 0; i < errorCorrectLength; i += 1) {\n      a = a.multiply(qrPolynomial([1, QRMath.gexp(i)], 0) );\n    }\n    return a;\n  };\n\n  _this.getLengthInBits = function(mode, type) {\n\n    if (1 <= type && type < 10) {\n\n      // 1 - 9\n\n      switch(mode) {\n      case QRMode.MODE_NUMBER    : return 10;\n      case QRMode.MODE_ALPHA_NUM : return 9;\n      case QRMode.MODE_8BIT_BYTE : return 8;\n      case QRMode.MODE_KANJI     : return 8;\n      default :\n        throw 'mode:' + mode;\n      }\n\n    } else if (type < 27) {\n\n      // 10 - 26\n\n      switch(mode) {\n      case QRMode.MODE_NUMBER    : return 12;\n      case QRMode.MODE_ALPHA_NUM : return 11;\n      case QRMode.MODE_8BIT_BYTE : return 16;\n      case QRMode.MODE_KANJI     : return 10;\n      default :\n        throw 'mode:' + mode;\n      }\n\n    } else if (type < 41) {\n\n      // 27 - 40\n\n      switch(mode) {\n      case QRMode.MODE_NUMBER    : return 14;\n      case QRMode.MODE_ALPHA_NUM : return 13;\n      case QRMode.MODE_8BIT_BYTE : return 16;\n      case QRMode.MODE_KANJI     : return 12;\n      default :\n        throw 'mode:' + mode;\n      }\n\n    } else {\n      throw 'type:' + type;\n    }\n  };\n\n  _this.getLostPoint = function(qrcode) {\n\n    const moduleCount = qrcode.getModuleCount();\n\n    let lostPoint = 0;\n\n    // LEVEL1\n\n    for (let row = 0; row < moduleCount; row += 1) {\n      for (let col = 0; col < moduleCount; col += 1) {\n\n        let sameCount = 0;\n        const dark = qrcode.isDark(row, col);\n\n        for (let r = -1; r <= 1; r += 1) {\n\n          if (row + r < 0 || moduleCount <= row + r) {\n            continue;\n          }\n\n          for (let c = -1; c <= 1; c += 1) {\n\n            if (col + c < 0 || moduleCount <= col + c) {\n              continue;\n            }\n\n            if (r == 0 && c == 0) {\n              continue;\n            }\n\n            if (dark == qrcode.isDark(row + r, col + c) ) {\n              sameCount += 1;\n            }\n          }\n        }\n\n        if (sameCount > 5) {\n          lostPoint += (3 + sameCount - 5);\n        }\n      }\n    };\n\n    // LEVEL2\n\n    for (let row = 0; row < moduleCount - 1; row += 1) {\n      for (let col = 0; col < moduleCount - 1; col += 1) {\n        let count = 0;\n        if (qrcode.isDark(row, col) ) count += 1;\n        if (qrcode.isDark(row + 1, col) ) count += 1;\n        if (qrcode.isDark(row, col + 1) ) count += 1;\n        if (qrcode.isDark(row + 1, col + 1) ) count += 1;\n        if (count == 0 || count == 4) {\n          lostPoint += 3;\n        }\n      }\n    }\n\n    // LEVEL3\n\n    for (let row = 0; row < moduleCount; row += 1) {\n      for (let col = 0; col < moduleCount - 6; col += 1) {\n        if (qrcode.isDark(row, col)\n            && !qrcode.isDark(row, col + 1)\n            &&  qrcode.isDark(row, col + 2)\n            &&  qrcode.isDark(row, col + 3)\n            &&  qrcode.isDark(row, col + 4)\n            && !qrcode.isDark(row, col + 5)\n            &&  qrcode.isDark(row, col + 6) ) {\n          lostPoint += 40;\n        }\n      }\n    }\n\n    for (let col = 0; col < moduleCount; col += 1) {\n      for (let row = 0; row < moduleCount - 6; row += 1) {\n        if (qrcode.isDark(row, col)\n            && !qrcode.isDark(row + 1, col)\n            &&  qrcode.isDark(row + 2, col)\n            &&  qrcode.isDark(row + 3, col)\n            &&  qrcode.isDark(row + 4, col)\n            && !qrcode.isDark(row + 5, col)\n            &&  qrcode.isDark(row + 6, col) ) {\n          lostPoint += 40;\n        }\n      }\n    }\n\n    // LEVEL4\n\n    let darkCount = 0;\n\n    for (let col = 0; col < moduleCount; col += 1) {\n      for (let row = 0; row < moduleCount; row += 1) {\n        if (qrcode.isDark(row, col) ) {\n          darkCount += 1;\n        }\n      }\n    }\n\n    const ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;\n    lostPoint += ratio * 10;\n\n    return lostPoint;\n  };\n\n  return _this;\n}();\n\n//---------------------------------------------------------------------\n// QRMath\n//---------------------------------------------------------------------\n\nconst QRMath = function() {\n\n  const EXP_TABLE = new Array(256);\n  const LOG_TABLE = new Array(256);\n\n  // initialize tables\n  for (let i = 0; i < 8; i += 1) {\n    EXP_TABLE[i] = 1 << i;\n  }\n  for (let i = 8; i < 256; i += 1) {\n    EXP_TABLE[i] = EXP_TABLE[i - 4]\n      ^ EXP_TABLE[i - 5]\n      ^ EXP_TABLE[i - 6]\n      ^ EXP_TABLE[i - 8];\n  }\n  for (let i = 0; i < 255; i += 1) {\n    LOG_TABLE[EXP_TABLE[i] ] = i;\n  }\n\n  const _this = {};\n\n  _this.glog = function(n) {\n\n    if (n < 1) {\n      throw 'glog(' + n + ')';\n    }\n\n    return LOG_TABLE[n];\n  };\n\n  _this.gexp = function(n) {\n\n    while (n < 0) {\n      n += 255;\n    }\n\n    while (n >= 256) {\n      n -= 255;\n    }\n\n    return EXP_TABLE[n];\n  };\n\n  return _this;\n}();\n\n//---------------------------------------------------------------------\n// qrPolynomial\n//---------------------------------------------------------------------\n\nconst qrPolynomial = function(num, shift) {\n\n  if (typeof num.length == 'undefined') {\n    throw num.length + '/' + shift;\n  }\n\n  const _num = function() {\n    let offset = 0;\n    while (offset < num.length && num[offset] == 0) {\n      offset += 1;\n    }\n    const _num = new Array(num.length - offset + shift);\n    for (let i = 0; i < num.length - offset; i += 1) {\n      _num[i] = num[i + offset];\n    }\n    return _num;\n  }();\n\n  const _this = {};\n\n  _this.getAt = function(index) {\n    return _num[index];\n  };\n\n  _this.getLength = function() {\n    return _num.length;\n  };\n\n  _this.multiply = function(e) {\n\n    const num = new Array(_this.getLength() + e.getLength() - 1);\n\n    for (let i = 0; i < _this.getLength(); i += 1) {\n      for (let j = 0; j < e.getLength(); j += 1) {\n        num[i + j] ^= QRMath.gexp(QRMath.glog(_this.getAt(i) ) + QRMath.glog(e.getAt(j) ) );\n      }\n    }\n\n    return qrPolynomial(num, 0);\n  };\n\n  _this.mod = function(e) {\n\n    if (_this.getLength() - e.getLength() < 0) {\n      return _this;\n    }\n\n    const ratio = QRMath.glog(_this.getAt(0) ) - QRMath.glog(e.getAt(0) );\n\n    const num = new Array(_this.getLength() );\n    for (let i = 0; i < _this.getLength(); i += 1) {\n      num[i] = _this.getAt(i);\n    }\n\n    for (let i = 0; i < e.getLength(); i += 1) {\n      num[i] ^= QRMath.gexp(QRMath.glog(e.getAt(i) ) + ratio);\n    }\n\n    // recursive call\n    return qrPolynomial(num, 0).mod(e);\n  };\n\n  return _this;\n};\n\n//---------------------------------------------------------------------\n// QRRSBlock\n//---------------------------------------------------------------------\n\nconst QRRSBlock = function() {\n\n  const RS_BLOCK_TABLE = [\n\n    // L\n    // M\n    // Q\n    // H\n\n    // 1\n    [1, 26, 19],\n    [1, 26, 16],\n    [1, 26, 13],\n    [1, 26, 9],\n\n    // 2\n    [1, 44, 34],\n    [1, 44, 28],\n    [1, 44, 22],\n    [1, 44, 16],\n\n    // 3\n    [1, 70, 55],\n    [1, 70, 44],\n    [2, 35, 17],\n    [2, 35, 13],\n\n    // 4\n    [1, 100, 80],\n    [2, 50, 32],\n    [2, 50, 24],\n    [4, 25, 9],\n\n    // 5\n    [1, 134, 108],\n    [2, 67, 43],\n    [2, 33, 15, 2, 34, 16],\n    [2, 33, 11, 2, 34, 12],\n\n    // 6\n    [2, 86, 68],\n    [4, 43, 27],\n    [4, 43, 19],\n    [4, 43, 15],\n\n    // 7\n    [2, 98, 78],\n    [4, 49, 31],\n    [2, 32, 14, 4, 33, 15],\n    [4, 39, 13, 1, 40, 14],\n\n    // 8\n    [2, 121, 97],\n    [2, 60, 38, 2, 61, 39],\n    [4, 40, 18, 2, 41, 19],\n    [4, 40, 14, 2, 41, 15],\n\n    // 9\n    [2, 146, 116],\n    [3, 58, 36, 2, 59, 37],\n    [4, 36, 16, 4, 37, 17],\n    [4, 36, 12, 4, 37, 13],\n\n    // 10\n    [2, 86, 68, 2, 87, 69],\n    [4, 69, 43, 1, 70, 44],\n    [6, 43, 19, 2, 44, 20],\n    [6, 43, 15, 2, 44, 16],\n\n    // 11\n    [4, 101, 81],\n    [1, 80, 50, 4, 81, 51],\n    [4, 50, 22, 4, 51, 23],\n    [3, 36, 12, 8, 37, 13],\n\n    // 12\n    [2, 116, 92, 2, 117, 93],\n    [6, 58, 36, 2, 59, 37],\n    [4, 46, 20, 6, 47, 21],\n    [7, 42, 14, 4, 43, 15],\n\n    // 13\n    [4, 133, 107],\n    [8, 59, 37, 1, 60, 38],\n    [8, 44, 20, 4, 45, 21],\n    [12, 33, 11, 4, 34, 12],\n\n    // 14\n    [3, 145, 115, 1, 146, 116],\n    [4, 64, 40, 5, 65, 41],\n    [11, 36, 16, 5, 37, 17],\n    [11, 36, 12, 5, 37, 13],\n\n    // 15\n    [5, 109, 87, 1, 110, 88],\n    [5, 65, 41, 5, 66, 42],\n    [5, 54, 24, 7, 55, 25],\n    [11, 36, 12, 7, 37, 13],\n\n    // 16\n    [5, 122, 98, 1, 123, 99],\n    [7, 73, 45, 3, 74, 46],\n    [15, 43, 19, 2, 44, 20],\n    [3, 45, 15, 13, 46, 16],\n\n    // 17\n    [1, 135, 107, 5, 136, 108],\n    [10, 74, 46, 1, 75, 47],\n    [1, 50, 22, 15, 51, 23],\n    [2, 42, 14, 17, 43, 15],\n\n    // 18\n    [5, 150, 120, 1, 151, 121],\n    [9, 69, 43, 4, 70, 44],\n    [17, 50, 22, 1, 51, 23],\n    [2, 42, 14, 19, 43, 15],\n\n    // 19\n    [3, 141, 113, 4, 142, 114],\n    [3, 70, 44, 11, 71, 45],\n    [17, 47, 21, 4, 48, 22],\n    [9, 39, 13, 16, 40, 14],\n\n    // 20\n    [3, 135, 107, 5, 136, 108],\n    [3, 67, 41, 13, 68, 42],\n    [15, 54, 24, 5, 55, 25],\n    [15, 43, 15, 10, 44, 16],\n\n    // 21\n    [4, 144, 116, 4, 145, 117],\n    [17, 68, 42],\n    [17, 50, 22, 6, 51, 23],\n    [19, 46, 16, 6, 47, 17],\n\n    // 22\n    [2, 139, 111, 7, 140, 112],\n    [17, 74, 46],\n    [7, 54, 24, 16, 55, 25],\n    [34, 37, 13],\n\n    // 23\n    [4, 151, 121, 5, 152, 122],\n    [4, 75, 47, 14, 76, 48],\n    [11, 54, 24, 14, 55, 25],\n    [16, 45, 15, 14, 46, 16],\n\n    // 24\n    [6, 147, 117, 4, 148, 118],\n    [6, 73, 45, 14, 74, 46],\n    [11, 54, 24, 16, 55, 25],\n    [30, 46, 16, 2, 47, 17],\n\n    // 25\n    [8, 132, 106, 4, 133, 107],\n    [8, 75, 47, 13, 76, 48],\n    [7, 54, 24, 22, 55, 25],\n    [22, 45, 15, 13, 46, 16],\n\n    // 26\n    [10, 142, 114, 2, 143, 115],\n    [19, 74, 46, 4, 75, 47],\n    [28, 50, 22, 6, 51, 23],\n    [33, 46, 16, 4, 47, 17],\n\n    // 27\n    [8, 152, 122, 4, 153, 123],\n    [22, 73, 45, 3, 74, 46],\n    [8, 53, 23, 26, 54, 24],\n    [12, 45, 15, 28, 46, 16],\n\n    // 28\n    [3, 147, 117, 10, 148, 118],\n    [3, 73, 45, 23, 74, 46],\n    [4, 54, 24, 31, 55, 25],\n    [11, 45, 15, 31, 46, 16],\n\n    // 29\n    [7, 146, 116, 7, 147, 117],\n    [21, 73, 45, 7, 74, 46],\n    [1, 53, 23, 37, 54, 24],\n    [19, 45, 15, 26, 46, 16],\n\n    // 30\n    [5, 145, 115, 10, 146, 116],\n    [19, 75, 47, 10, 76, 48],\n    [15, 54, 24, 25, 55, 25],\n    [23, 45, 15, 25, 46, 16],\n\n    // 31\n    [13, 145, 115, 3, 146, 116],\n    [2, 74, 46, 29, 75, 47],\n    [42, 54, 24, 1, 55, 25],\n    [23, 45, 15, 28, 46, 16],\n\n    // 32\n    [17, 145, 115],\n    [10, 74, 46, 23, 75, 47],\n    [10, 54, 24, 35, 55, 25],\n    [19, 45, 15, 35, 46, 16],\n\n    // 33\n    [17, 145, 115, 1, 146, 116],\n    [14, 74, 46, 21, 75, 47],\n    [29, 54, 24, 19, 55, 25],\n    [11, 45, 15, 46, 46, 16],\n\n    // 34\n    [13, 145, 115, 6, 146, 116],\n    [14, 74, 46, 23, 75, 47],\n    [44, 54, 24, 7, 55, 25],\n    [59, 46, 16, 1, 47, 17],\n\n    // 35\n    [12, 151, 121, 7, 152, 122],\n    [12, 75, 47, 26, 76, 48],\n    [39, 54, 24, 14, 55, 25],\n    [22, 45, 15, 41, 46, 16],\n\n    // 36\n    [6, 151, 121, 14, 152, 122],\n    [6, 75, 47, 34, 76, 48],\n    [46, 54, 24, 10, 55, 25],\n    [2, 45, 15, 64, 46, 16],\n\n    // 37\n    [17, 152, 122, 4, 153, 123],\n    [29, 74, 46, 14, 75, 47],\n    [49, 54, 24, 10, 55, 25],\n    [24, 45, 15, 46, 46, 16],\n\n    // 38\n    [4, 152, 122, 18, 153, 123],\n    [13, 74, 46, 32, 75, 47],\n    [48, 54, 24, 14, 55, 25],\n    [42, 45, 15, 32, 46, 16],\n\n    // 39\n    [20, 147, 117, 4, 148, 118],\n    [40, 75, 47, 7, 76, 48],\n    [43, 54, 24, 22, 55, 25],\n    [10, 45, 15, 67, 46, 16],\n\n    // 40\n    [19, 148, 118, 6, 149, 119],\n    [18, 75, 47, 31, 76, 48],\n    [34, 54, 24, 34, 55, 25],\n    [20, 45, 15, 61, 46, 16]\n  ];\n\n  const qrRSBlock = function(totalCount, dataCount) {\n    const _this = {};\n    _this.totalCount = totalCount;\n    _this.dataCount = dataCount;\n    return _this;\n  };\n\n  const _this = {};\n\n  const getRsBlockTable = function(typeNumber, errorCorrectionLevel) {\n\n    switch(errorCorrectionLevel) {\n    case QRErrorCorrectionLevel.L :\n      return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];\n    case QRErrorCorrectionLevel.M :\n      return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];\n    case QRErrorCorrectionLevel.Q :\n      return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];\n    case QRErrorCorrectionLevel.H :\n      return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];\n    default :\n      return undefined;\n    }\n  };\n\n  _this.getRSBlocks = function(typeNumber, errorCorrectionLevel) {\n\n    const rsBlock = getRsBlockTable(typeNumber, errorCorrectionLevel);\n\n    if (typeof rsBlock == 'undefined') {\n      throw 'bad rs block @ typeNumber:' + typeNumber +\n          '/errorCorrectionLevel:' + errorCorrectionLevel;\n    }\n\n    const length = rsBlock.length / 3;\n\n    const list = [];\n\n    for (let i = 0; i < length; i += 1) {\n\n      const count = rsBlock[i * 3 + 0];\n      const totalCount = rsBlock[i * 3 + 1];\n      const dataCount = rsBlock[i * 3 + 2];\n\n      for (let j = 0; j < count; j += 1) {\n        list.push(qrRSBlock(totalCount, dataCount) );\n      }\n    }\n\n    return list;\n  };\n\n  return _this;\n}();\n\n//---------------------------------------------------------------------\n// qrBitBuffer\n//---------------------------------------------------------------------\n\nconst qrBitBuffer = function() {\n\n  const _buffer = [];\n  let _length = 0;\n\n  const _this = {};\n\n  _this.getBuffer = function() {\n    return _buffer;\n  };\n\n  _this.getAt = function(index) {\n    const bufIndex = Math.floor(index / 8);\n    return ( (_buffer[bufIndex] >>> (7 - index % 8) ) & 1) == 1;\n  };\n\n  _this.put = function(num, length) {\n    for (let i = 0; i < length; i += 1) {\n      _this.putBit( ( (num >>> (length - i - 1) ) & 1) == 1);\n    }\n  };\n\n  _this.getLengthInBits = function() {\n    return _length;\n  };\n\n  _this.putBit = function(bit) {\n\n    const bufIndex = Math.floor(_length / 8);\n    if (_buffer.length <= bufIndex) {\n      _buffer.push(0);\n    }\n\n    if (bit) {\n      _buffer[bufIndex] |= (0x80 >>> (_length % 8) );\n    }\n\n    _length += 1;\n  };\n\n  return _this;\n};\n\n//---------------------------------------------------------------------\n// qrNumber\n//---------------------------------------------------------------------\n\nconst qrNumber = function(data) {\n\n  const _mode = QRMode.MODE_NUMBER;\n  const _data = data;\n\n  const _this = {};\n\n  _this.getMode = function() {\n    return _mode;\n  };\n\n  _this.getLength = function(buffer) {\n    return _data.length;\n  };\n\n  _this.write = function(buffer) {\n\n    const data = _data;\n\n    let i = 0;\n\n    while (i + 2 < data.length) {\n      buffer.put(strToNum(data.substring(i, i + 3) ), 10);\n      i += 3;\n    }\n\n    if (i < data.length) {\n      if (data.length - i == 1) {\n        buffer.put(strToNum(data.substring(i, i + 1) ), 4);\n      } else if (data.length - i == 2) {\n        buffer.put(strToNum(data.substring(i, i + 2) ), 7);\n      }\n    }\n  };\n\n  const strToNum = function(s) {\n    let num = 0;\n    for (let i = 0; i < s.length; i += 1) {\n      num = num * 10 + chatToNum(s.charAt(i) );\n    }\n    return num;\n  };\n\n  const chatToNum = function(c) {\n    if ('0' <= c && c <= '9') {\n      return c.charCodeAt(0) - '0'.charCodeAt(0);\n    }\n    throw 'illegal char :' + c;\n  };\n\n  return _this;\n};\n\n//---------------------------------------------------------------------\n// qrAlphaNum\n//---------------------------------------------------------------------\n\nconst qrAlphaNum = function(data) {\n\n  const _mode = QRMode.MODE_ALPHA_NUM;\n  const _data = data;\n\n  const _this = {};\n\n  _this.getMode = function() {\n    return _mode;\n  };\n\n  _this.getLength = function(buffer) {\n    return _data.length;\n  };\n\n  _this.write = function(buffer) {\n\n    const s = _data;\n\n    let i = 0;\n\n    while (i + 1 < s.length) {\n      buffer.put(\n        getCode(s.charAt(i) ) * 45 +\n        getCode(s.charAt(i + 1) ), 11);\n      i += 2;\n    }\n\n    if (i < s.length) {\n      buffer.put(getCode(s.charAt(i) ), 6);\n    }\n  };\n\n  const getCode = function(c) {\n\n    if ('0' <= c && c <= '9') {\n      return c.charCodeAt(0) - '0'.charCodeAt(0);\n    } else if ('A' <= c && c <= 'Z') {\n      return c.charCodeAt(0) - 'A'.charCodeAt(0) + 10;\n    } else {\n      switch (c) {\n      case '\\u0020' : return 36;\n      case '$' : return 37;\n      case '%' : return 38;\n      case '*' : return 39;\n      case '+' : return 40;\n      case '-' : return 41;\n      case '.' : return 42;\n      case '/' : return 43;\n      case ':' : return 44;\n      default :\n        throw 'illegal char :' + c;\n      }\n    }\n  };\n\n  return _this;\n};\n\n//---------------------------------------------------------------------\n// qr8BitByte\n//---------------------------------------------------------------------\n\nconst qr8BitByte = function(data) {\n\n  const _mode = QRMode.MODE_8BIT_BYTE;\n  const _data = data;\n  const _bytes = qrcode.stringToBytes(data);\n\n  const _this = {};\n\n  _this.getMode = function() {\n    return _mode;\n  };\n\n  _this.getLength = function(buffer) {\n    return _bytes.length;\n  };\n\n  _this.write = function(buffer) {\n    for (let i = 0; i < _bytes.length; i += 1) {\n      buffer.put(_bytes[i], 8);\n    }\n  };\n\n  return _this;\n};\n\n//---------------------------------------------------------------------\n// qrKanji\n//---------------------------------------------------------------------\n\nconst qrKanji = function(data) {\n\n  const _mode = QRMode.MODE_KANJI;\n  const _data = data;\n\n  const stringToBytes = qrcode.stringToBytes;\n  !function(c, code) {\n    // self test for sjis support.\n    const test = stringToBytes(c);\n    if (test.length != 2 || ( (test[0] << 8) | test[1]) != code) {\n      throw 'sjis not supported.';\n    }\n  }('\\u53cb', 0x9746);\n\n  const _bytes = stringToBytes(data);\n\n  const _this = {};\n\n  _this.getMode = function() {\n    return _mode;\n  };\n\n  _this.getLength = function(buffer) {\n    return ~~(_bytes.length / 2);\n  };\n\n  _this.write = function(buffer) {\n\n    const data = _bytes;\n\n    let i = 0;\n\n    while (i + 1 < data.length) {\n\n      let c = ( (0xff & data[i]) << 8) | (0xff & data[i + 1]);\n\n      if (0x8140 <= c && c <= 0x9FFC) {\n        c -= 0x8140;\n      } else if (0xE040 <= c && c <= 0xEBBF) {\n        c -= 0xC140;\n      } else {\n        throw 'illegal char at ' + (i + 1) + '/' + c;\n      }\n\n      c = ( (c >>> 8) & 0xff) * 0xC0 + (c & 0xff);\n\n      buffer.put(c, 13);\n\n      i += 2;\n    }\n\n    if (i < data.length) {\n      throw 'illegal char at ' + (i + 1);\n    }\n  };\n\n  return _this;\n};\n\n//=====================================================================\n// GIF Support etc.\n//\n\n//---------------------------------------------------------------------\n// byteArrayOutputStream\n//---------------------------------------------------------------------\n\nconst byteArrayOutputStream = function() {\n\n  const _bytes = [];\n\n  const _this = {};\n\n  _this.writeByte = function(b) {\n    _bytes.push(b & 0xff);\n  };\n\n  _this.writeShort = function(i) {\n    _this.writeByte(i);\n    _this.writeByte(i >>> 8);\n  };\n\n  _this.writeBytes = function(b, off, len) {\n    off = off || 0;\n    len = len || b.length;\n    for (let i = 0; i < len; i += 1) {\n      _this.writeByte(b[i + off]);\n    }\n  };\n\n  _this.writeString = function(s) {\n    for (let i = 0; i < s.length; i += 1) {\n      _this.writeByte(s.charCodeAt(i) );\n    }\n  };\n\n  _this.toByteArray = function() {\n    return _bytes;\n  };\n\n  _this.toString = function() {\n    let s = '';\n    s += '[';\n    for (let i = 0; i < _bytes.length; i += 1) {\n      if (i > 0) {\n        s += ',';\n      }\n      s += _bytes[i];\n    }\n    s += ']';\n    return s;\n  };\n\n  return _this;\n};\n\n//---------------------------------------------------------------------\n// base64EncodeOutputStream\n//---------------------------------------------------------------------\n\nconst base64EncodeOutputStream = function() {\n\n  let _buffer = 0;\n  let _buflen = 0;\n  let _length = 0;\n  let _base64 = '';\n\n  const _this = {};\n\n  const writeEncoded = function(b) {\n    _base64 += String.fromCharCode(encode(b & 0x3f) );\n  };\n\n  const encode = function(n) {\n    if (n < 0) {\n      throw 'n:' + n;\n    } else if (n < 26) {\n      return 0x41 + n;\n    } else if (n < 52) {\n      return 0x61 + (n - 26);\n    } else if (n < 62) {\n      return 0x30 + (n - 52);\n    } else if (n == 62) {\n      return 0x2b;\n    } else if (n == 63) {\n      return 0x2f;\n    } else {\n      throw 'n:' + n;\n    }\n  };\n\n  _this.writeByte = function(n) {\n\n    _buffer = (_buffer << 8) | (n & 0xff);\n    _buflen += 8;\n    _length += 1;\n\n    while (_buflen >= 6) {\n      writeEncoded(_buffer >>> (_buflen - 6) );\n      _buflen -= 6;\n    }\n  };\n\n  _this.flush = function() {\n\n    if (_buflen > 0) {\n      writeEncoded(_buffer << (6 - _buflen) );\n      _buffer = 0;\n      _buflen = 0;\n    }\n\n    if (_length % 3 != 0) {\n      // padding\n      const padlen = 3 - _length % 3;\n      for (let i = 0; i < padlen; i += 1) {\n        _base64 += '=';\n      }\n    }\n  };\n\n  _this.toString = function() {\n    return _base64;\n  };\n\n  return _this;\n};\n\n//---------------------------------------------------------------------\n// base64DecodeInputStream\n//---------------------------------------------------------------------\n\nconst base64DecodeInputStream = function(str) {\n\n  const _str = str;\n  let _pos = 0;\n  let _buffer = 0;\n  let _buflen = 0;\n\n  const _this = {};\n\n  _this.read = function() {\n\n    while (_buflen < 8) {\n\n      if (_pos >= _str.length) {\n        if (_buflen == 0) {\n          return -1;\n        }\n        throw 'unexpected end of file./' + _buflen;\n      }\n\n      const c = _str.charAt(_pos);\n      _pos += 1;\n\n      if (c == '=') {\n        _buflen = 0;\n        return -1;\n      } else if (c.match(/^\\s$/) ) {\n        // ignore if whitespace.\n        continue;\n      }\n\n      _buffer = (_buffer << 6) | decode(c.charCodeAt(0) );\n      _buflen += 6;\n    }\n\n    const n = (_buffer >>> (_buflen - 8) ) & 0xff;\n    _buflen -= 8;\n    return n;\n  };\n\n  const decode = function(c) {\n    if (0x41 <= c && c <= 0x5a) {\n      return c - 0x41;\n    } else if (0x61 <= c && c <= 0x7a) {\n      return c - 0x61 + 26;\n    } else if (0x30 <= c && c <= 0x39) {\n      return c - 0x30 + 52;\n    } else if (c == 0x2b) {\n      return 62;\n    } else if (c == 0x2f) {\n      return 63;\n    } else {\n      throw 'c:' + c;\n    }\n  };\n\n  return _this;\n};\n\n//---------------------------------------------------------------------\n// gifImage (B/W)\n//---------------------------------------------------------------------\n\nconst gifImage = function(width, height) {\n\n  const _width = width;\n  const _height = height;\n  const _data = new Array(width * height);\n\n  const _this = {};\n\n  _this.setPixel = function(x, y, pixel) {\n    _data[y * _width + x] = pixel;\n  };\n\n  _this.write = function(out) {\n\n    //---------------------------------\n    // GIF Signature\n\n    out.writeString('GIF87a');\n\n    //---------------------------------\n    // Screen Descriptor\n\n    out.writeShort(_width);\n    out.writeShort(_height);\n\n    out.writeByte(0x80); // 2bit\n    out.writeByte(0);\n    out.writeByte(0);\n\n    //---------------------------------\n    // Global Color Map\n\n    // black\n    out.writeByte(0x00);\n    out.writeByte(0x00);\n    out.writeByte(0x00);\n\n    // white\n    out.writeByte(0xff);\n    out.writeByte(0xff);\n    out.writeByte(0xff);\n\n    //---------------------------------\n    // Image Descriptor\n\n    out.writeString(',');\n    out.writeShort(0);\n    out.writeShort(0);\n    out.writeShort(_width);\n    out.writeShort(_height);\n    out.writeByte(0);\n\n    //---------------------------------\n    // Local Color Map\n\n    //---------------------------------\n    // Raster Data\n\n    const lzwMinCodeSize = 2;\n    const raster = getLZWRaster(lzwMinCodeSize);\n\n    out.writeByte(lzwMinCodeSize);\n\n    let offset = 0;\n\n    while (raster.length - offset > 255) {\n      out.writeByte(255);\n      out.writeBytes(raster, offset, 255);\n      offset += 255;\n    }\n\n    out.writeByte(raster.length - offset);\n    out.writeBytes(raster, offset, raster.length - offset);\n    out.writeByte(0x00);\n\n    //---------------------------------\n    // GIF Terminator\n    out.writeString(';');\n  };\n\n  const bitOutputStream = function(out) {\n\n    const _out = out;\n    let _bitLength = 0;\n    let _bitBuffer = 0;\n\n    const _this = {};\n\n    _this.write = function(data, length) {\n\n      if ( (data >>> length) != 0) {\n        throw 'length over';\n      }\n\n      while (_bitLength + length >= 8) {\n        _out.writeByte(0xff & ( (data << _bitLength) | _bitBuffer) );\n        length -= (8 - _bitLength);\n        data >>>= (8 - _bitLength);\n        _bitBuffer = 0;\n        _bitLength = 0;\n      }\n\n      _bitBuffer = (data << _bitLength) | _bitBuffer;\n      _bitLength = _bitLength + length;\n    };\n\n    _this.flush = function() {\n      if (_bitLength > 0) {\n        _out.writeByte(_bitBuffer);\n      }\n    };\n\n    return _this;\n  };\n\n  const getLZWRaster = function(lzwMinCodeSize) {\n\n    const clearCode = 1 << lzwMinCodeSize;\n    const endCode = (1 << lzwMinCodeSize) + 1;\n    let bitLength = lzwMinCodeSize + 1;\n\n    // Setup LZWTable\n    const table = lzwTable();\n\n    for (let i = 0; i < clearCode; i += 1) {\n      table.add(String.fromCharCode(i) );\n    }\n    table.add(String.fromCharCode(clearCode) );\n    table.add(String.fromCharCode(endCode) );\n\n    const byteOut = byteArrayOutputStream();\n    const bitOut = bitOutputStream(byteOut);\n\n    // clear code\n    bitOut.write(clearCode, bitLength);\n\n    let dataIndex = 0;\n\n    let s = String.fromCharCode(_data[dataIndex]);\n    dataIndex += 1;\n\n    while (dataIndex < _data.length) {\n\n      const c = String.fromCharCode(_data[dataIndex]);\n      dataIndex += 1;\n\n      if (table.contains(s + c) ) {\n\n        s = s + c;\n\n      } else {\n\n        bitOut.write(table.indexOf(s), bitLength);\n\n        if (table.size() < 0xfff) {\n\n          if (table.size() == (1 << bitLength) ) {\n            bitLength += 1;\n          }\n\n          table.add(s + c);\n        }\n\n        s = c;\n      }\n    }\n\n    bitOut.write(table.indexOf(s), bitLength);\n\n    // end code\n    bitOut.write(endCode, bitLength);\n\n    bitOut.flush();\n\n    return byteOut.toByteArray();\n  };\n\n  const lzwTable = function() {\n\n    const _map = {};\n    let _size = 0;\n\n    const _this = {};\n\n    _this.add = function(key) {\n      if (_this.contains(key) ) {\n        throw 'dup key:' + key;\n      }\n      _map[key] = _size;\n      _size += 1;\n    };\n\n    _this.size = function() {\n      return _size;\n    };\n\n    _this.indexOf = function(key) {\n      return _map[key];\n    };\n\n    _this.contains = function(key) {\n      return typeof _map[key] != 'undefined';\n    };\n\n    return _this;\n  };\n\n  return _this;\n};\n\nconst createDataURL = function(width, height, getPixel) {\n  const gif = gifImage(width, height);\n  for (let y = 0; y < height; y += 1) {\n    for (let x = 0; x < width; x += 1) {\n      gif.setPixel(x, y, getPixel(x, y) );\n    }\n  }\n\n  const b = byteArrayOutputStream();\n  gif.write(b);\n\n  const base64 = base64EncodeOutputStream();\n  const bytes = b.toByteArray();\n  for (let i = 0; i < bytes.length; i += 1) {\n    base64.writeByte(bytes[i]);\n  }\n  base64.flush();\n\n  return 'data:image/gif;base64,' + base64;\n};\n\nexport default qrcode;\n\nexport const stringToBytes = qrcode.stringToBytes;\n", "// LiveView hooks for \"Waiting For The Popcorn\" (/popcorn, /popcorn/tv).\n//\n// The server is authoritative; these hooks only do what a server render can't:\n//   PopcornTv       \u2013 tell the TV LiveView its origin so the join URL/QR point\n//                     at whatever host the TV is on (loor.tv, staging, LAN dev).\n//   PopcornQr       \u2013 draw the join QR code client-side (no server dependency).\n//   PopcornIdentity \u2013 keep a phone's player id + name in localStorage so a phone\n//                     that sleeps or reconnects silently rejoins its seat.\n//   PopcornTimers   \u2013 animate chess cooldown sweeps + the round countdown\n//                     between server pushes. The server sends REMAINING\n//                     durations; we extrapolate from the moment we received\n//                     them using only this device's clock (skew-proof).\nimport qrcode from 'qrcode-generator'\n\nconst store = {\n  get(key) {\n    try {\n      return window.localStorage.getItem(key)\n    } catch (_e) {\n      return null\n    }\n  },\n  set(key, value) {\n    try {\n      window.localStorage.setItem(key, value)\n    } catch (_e) {\n      /* private mode etc. \u2014 rejoin just won't be automatic */\n    }\n  },\n}\n\nconst PopcornTv = {\n  mounted() {\n    this.hello()\n  },\n  reconnected() {\n    this.hello()\n  },\n  hello() {\n    this.pushEvent('tv:hello', { origin: window.location.origin })\n  },\n}\n\nconst PopcornQr = {\n  mounted() {\n    const url = this.el.dataset.url\n    if (!url) return\n    const qr = qrcode(0, 'M')\n    qr.addData(url)\n    qr.make()\n    // Ink modules on a cream tile: on-palette but still high-contrast to scan.\n    this.el.innerHTML = qr\n      .createSvgTag({ cellSize: 8, margin: 2, scalable: true })\n      .replace(/fill=\"black\"/g, 'fill=\"#07070F\"')\n      .replace(/fill=\"white\"/g, 'fill=\"#F2EDE4\"')\n  },\n}\n\nconst PopcornIdentity = {\n  mounted() {\n    this.handleEvent('popcorn:remember', ({ player_id, name }) => {\n      if (player_id) store.set('popcorn_player_id', player_id)\n      if (name) store.set('popcorn_name', name)\n    })\n    this.identify()\n  },\n  reconnected() {\n    this.identify()\n  },\n  identify() {\n    this.pushEvent('identity', {\n      player_id: store.get('popcorn_player_id'),\n      name: store.get('popcorn_name') || '',\n    })\n  },\n}\n\nconst PopcornTimers = {\n  mounted() {\n    this.sync()\n    this.timer = setInterval(() => this.paint(), 80)\n  },\n  updated() {\n    this.sync()\n  },\n  destroyed() {\n    clearInterval(this.timer)\n  },\n  sync() {\n    this.receivedAt = performance.now()\n    // The countdown keeps a local end-time per round so repeated pushes\n    // can't reset or extend it.\n    const cd = this.el.querySelector('[data-countdown]')\n    const remaining = cd ? Number(cd.dataset.countdown || 0) : 0\n    this.countdownEndsAt = remaining > 0 ? this.receivedAt + remaining : 0\n    this.paint()\n  },\n  paint() {\n    const now = performance.now()\n    const elapsed = now - this.receivedAt\n\n    this.el.querySelectorAll('.pc-cool').forEach((fill) => {\n      const left = Math.max(0, Number(fill.dataset.cd || 0) - elapsed)\n      const total = Number(fill.dataset.cdms || 2500)\n      const pct = left > 0 ? Math.min(1, left / total) * 100 : 0\n      fill.style.height = pct + '%'\n      fill.parentElement.classList.toggle('pc-sq--cool', left > 0)\n    })\n\n    const cd = this.el.querySelector('[data-countdown]')\n    if (cd) {\n      const left = this.countdownEndsAt ? Math.max(0, this.countdownEndsAt - now) : 0\n      cd.hidden = left <= 0\n      if (left > 0) cd.textContent = Math.ceil(left / 1000)\n    }\n  },\n}\n\n// A round clock (m:ss) rendered entirely in the browser. The server sends the\n// REMAINING milliseconds with each push (accurate at that moment); we count down\n// locally from the instant we received it, so the clock stays smooth without the\n// server having to broadcast once a second. Re-syncs on every push, so it never\n// drifts from the authoritative round end.\nconst PopcornClock = {\n  mounted() {\n    this.sync()\n    this.timer = setInterval(() => this.paint(), 250)\n  },\n  updated() {\n    this.sync()\n  },\n  destroyed() {\n    clearInterval(this.timer)\n  },\n  sync() {\n    const remaining = Number(this.el.dataset.remaining || 0)\n    this.endsAt = performance.now() + Math.max(0, remaining)\n    this.paint()\n  },\n  paint() {\n    const left = Math.max(0, this.endsAt - performance.now())\n    const total = Math.round(left / 1000)\n    const mins = Math.floor(total / 60)\n    const secs = String(total % 60).padStart(2, '0')\n    this.el.textContent = `${mins}:${secs}`\n  },\n}\n\n// Synthesised, theme-appropriate sound \u2014 no audio files, so nothing to license\n// or download. Short retro blips for game events plus a gentle looping music\n// bed while a game is live, all generated with the Web Audio API. The server\n// pushes cues (\"popcorn:sfx\"/\"popcorn:music\"); this device decides whether to\n// play them (mute is per-device, remembered in localStorage). Taps on game\n// controls click instantly, client-side, for snappy feedback.\nconst SFX = {\n  tap: [{ freq: 660, type: 'square', dur: 0.05, gain: 0.1 }],\n  score: [\n    { freq: 659.25, dur: 0.09, gain: 0.2 },\n    { freq: 987.77, start: 0.09, dur: 0.13, gain: 0.2 },\n  ],\n  ding: [{ freq: 1046.5, type: 'triangle', dur: 0.18, gain: 0.16 }],\n  buzz: [{ freq: 160, type: 'sawtooth', dur: 0.18, gain: 0.16, slideTo: 110 }],\n  start: [\n    { freq: 523.25, dur: 0.08, gain: 0.18 },\n    { freq: 659.25, start: 0.08, dur: 0.08, gain: 0.18 },\n    { freq: 783.99, start: 0.16, dur: 0.13, gain: 0.18 },\n  ],\n  win: [\n    { freq: 523.25, dur: 0.1, gain: 0.2 },\n    { freq: 659.25, start: 0.1, dur: 0.1, gain: 0.2 },\n    { freq: 783.99, start: 0.2, dur: 0.1, gain: 0.2 },\n    { freq: 1046.5, start: 0.3, dur: 0.24, gain: 0.22 },\n  ],\n  fanfare: [\n    { freq: 392.0, dur: 0.12, gain: 0.2 },\n    { freq: 523.25, start: 0.12, dur: 0.12, gain: 0.2 },\n    { freq: 659.25, start: 0.24, dur: 0.12, gain: 0.2 },\n    { freq: 783.99, start: 0.36, dur: 0.28, gain: 0.22 },\n  ],\n  over: [\n    { freq: 440.0, dur: 0.14, gain: 0.16, slideTo: 330 },\n    { freq: 294.0, start: 0.14, dur: 0.26, gain: 0.16, slideTo: 220 },\n  ],\n}\n\n// Spot & Tap scene input: a plain tap sends a \"tap\" with the point (0\u2013100%\n// of the scene); dragging a blocker (an element with data-obscurer) sends\n// throttled \"move_obscurer\" updates so everyone sees it shift live.\nconst PopcornScene = {\n  mounted() {\n    this.dragId = null\n    this.lastSend = 0\n    this.moved = false\n\n    this.onDown = (e) => {\n      const ob = e.target.closest('[data-obscurer]')\n      this.moved = false\n      if (ob) {\n        this.dragId = ob.dataset.obscurer\n        e.preventDefault()\n      } else {\n        this.dragId = null\n      }\n    }\n\n    this.onMove = (e) => {\n      if (this.dragId === null) return\n      this.moved = true\n      e.preventDefault()\n      const now = performance.now()\n      if (now - this.lastSend < 55) return\n      this.lastSend = now\n      const { x, y } = this.point(e)\n      this.pushEvent('move_obscurer', { id: Number(this.dragId), x, y })\n    }\n\n    this.onUp = (e) => {\n      if (this.dragId !== null) {\n        if (this.moved) {\n          const { x, y } = this.point(e)\n          this.pushEvent('move_obscurer', { id: Number(this.dragId), x, y })\n        }\n        this.dragId = null\n      } else {\n        const { x, y } = this.point(e)\n        this.pushEvent('tap', { x, y })\n      }\n    }\n\n    this.el.addEventListener('pointerdown', this.onDown)\n    this.el.addEventListener('pointermove', this.onMove)\n    window.addEventListener('pointerup', this.onUp)\n  },\n  destroyed() {\n    this.el.removeEventListener('pointerdown', this.onDown)\n    this.el.removeEventListener('pointermove', this.onMove)\n    window.removeEventListener('pointerup', this.onUp)\n  },\n  point(e) {\n    const rect = this.el.getBoundingClientRect()\n    const clamp = (n) => Math.max(0, Math.min(100, n))\n    return {\n      x: Math.round(clamp(((e.clientX - rect.left) / rect.width) * 100) * 10) / 10,\n      y: Math.round(clamp(((e.clientY - rect.top) / rect.height) * 100) * 10) / 10,\n    }\n  },\n}\n\nconst PopcornAudio = {\n  mounted() {\n    this.muted = store.get('popcorn_muted') === '1'\n    this.wantMusic = false\n    this.ctx = null\n    this.musicStop = null\n    this.render()\n\n    // Autoplay policy: (re)create + resume the AudioContext on any gesture.\n    this._gesture = () => this.resume()\n    document.addEventListener('pointerdown', this._gesture, true)\n\n    // Instant local click when a game control is pressed.\n    this._tap = (e) => {\n      if (!this.muted && e.target.closest('.pc-tile--tap, .pc-order, .pc-card')) this.sfx('tap')\n    }\n    document.addEventListener('pointerdown', this._tap, true)\n\n    this.el.addEventListener('click', () => this.toggle())\n    this.handleEvent('popcorn:sfx', ({ name }) => this.sfx(name))\n    this.handleEvent('popcorn:music', ({ on }) => this.setMusic(on))\n  },\n  destroyed() {\n    document.removeEventListener('pointerdown', this._gesture, true)\n    document.removeEventListener('pointerdown', this._tap, true)\n    this.stopMusic()\n  },\n  render() {\n    this.el.textContent = this.muted ? '\uD83D\uDD07' : '\uD83D\uDD0A'\n    this.el.setAttribute('aria-pressed', this.muted ? 'true' : 'false')\n  },\n  toggle() {\n    this.muted = !this.muted\n    store.set('popcorn_muted', this.muted ? '1' : '0')\n    if (this.muted) this.stopMusic()\n    else this.resume()\n    this.render()\n  },\n  ctxReady() {\n    if (!this.ctx) {\n      const AC = window.AudioContext || window.webkitAudioContext\n      if (!AC) return null\n      this.ctx = new AC()\n    }\n    return this.ctx\n  },\n  resume() {\n    const ctx = this.ctxReady()\n    if (ctx && ctx.state === 'suspended') ctx.resume()\n    if (!this.muted && this.wantMusic && !this.musicStop) this.startMusic()\n  },\n  note(ctx, { freq, type = 'square', start = 0, dur = 0.12, gain = 0.2, slideTo = null, dest = null }) {\n    const t0 = ctx.currentTime + start\n    const osc = ctx.createOscillator()\n    const g = ctx.createGain()\n    osc.type = type\n    osc.frequency.setValueAtTime(freq, t0)\n    if (slideTo) osc.frequency.exponentialRampToValueAtTime(slideTo, t0 + dur)\n    g.gain.setValueAtTime(0.0001, t0)\n    g.gain.exponentialRampToValueAtTime(gain, t0 + 0.012)\n    g.gain.exponentialRampToValueAtTime(0.0001, t0 + dur)\n    osc.connect(g).connect(dest || ctx.destination)\n    osc.start(t0)\n    osc.stop(t0 + dur + 0.03)\n  },\n  sfx(name) {\n    if (this.muted) return\n    const ctx = this.ctxReady()\n    if (!ctx) return\n    if (ctx.state === 'suspended') ctx.resume()\n    const seq = SFX[name]\n    if (seq) seq.forEach((n) => this.note(ctx, n))\n  },\n  setMusic(on) {\n    this.wantMusic = on\n    if (!on) this.stopMusic()\n    else if (!this.muted) this.resume()\n  },\n  startMusic() {\n    const ctx = this.ctxReady()\n    if (!ctx || this.musicStop) return\n\n    const bus = ctx.createGain()\n    bus.gain.value = 0.05\n    bus.connect(ctx.destination)\n\n    // Gentle looping pentatonic noodle + soft bass \u2014 never resolves \"wrong\".\n    const line = [392.0, 523.25, 587.33, 659.25, 783.99, 659.25, 587.33, 523.25]\n    const beat = 0.34\n    let i = 0\n    let next = ctx.currentTime + 0.1\n\n    const schedule = () => {\n      if (!this.musicStop) return\n      while (next < ctx.currentTime + 0.5) {\n        const at = next - ctx.currentTime\n        this.note(ctx, { freq: line[i % line.length], type: 'triangle', start: at, dur: beat * 0.9, gain: 0.5, dest: bus })\n        if (i % 4 === 0) this.note(ctx, { freq: 130.81, type: 'sine', start: at, dur: beat * 2, gain: 0.6, dest: bus })\n        next += beat\n        i++\n      }\n    }\n\n    const id = setInterval(schedule, 120)\n    this.musicStop = () => {\n      clearInterval(id)\n      try {\n        bus.disconnect()\n      } catch (_e) {\n        /* already gone */\n      }\n    }\n    schedule()\n  },\n  stopMusic() {\n    if (this.musicStop) {\n      this.musicStop()\n      this.musicStop = null\n    }\n  },\n}\n\n// Winner's share card: draw a PNG (trophy, score, LOOR mark, \"Waiting For\n// Popcorn\", game name) client-side, then offer native share or copy-image /\n// copy-text so the winner can post or text it anywhere. The link points back to\n// the movie's page when the party was launched from one.\nconst LOOT_PATH =\n  'M173.752 60.271l-13.98 60.72-79.965 20.089C10.252 158.553-.138 161.401.001 162.957c.088.984 3.855 16.581 8.372 34.661 5.84 23.379 8.611 32.873 9.596 32.873.761 0 28.621-6.81 61.911-15.133 33.291-8.324 60.717-14.944 60.949-14.713.312.312-64.678 283.993-70.354 307.096l-.92 3.75H384.34v-72H160.124l.528-2.25c.291-1.237 13.684-59.4 29.763-129.25s29.364-127.162 29.523-127.359c.159-.198 34.852-9.012 77.096-19.587 66.85-16.734 76.786-19.459 76.647-21.018-.088-.985-3.855-16.583-8.372-34.663-6.602-26.431-8.53-32.867-9.84-32.844-.895.015-27.494 6.512-59.109 14.436-31.614 7.924-57.622 14.265-57.796 14.091-.174-.174 4.057-19.268 9.402-42.431 5.345-23.163 9.49-42.343 9.211-42.622-.279-.279-15.094-3.875-32.922-7.991A37240.96 37240.96 0 01189.786.035c-1.945-.458-2.799 2.75-16.034 60.236zm128.589 153.203c-30.179 3.795-56.603 22.42-70.249 49.517-1.385 2.75-3.755 8.825-5.268 13.5-3.614 11.175-4.618 32.218-2.114 44.327 8.617 41.669 45.249 71.602 87.697 71.66 26.156.036 47.941-9.461 66.013-28.776 8.271-8.84 12.474-15.324 17.434-26.892 8.629-20.128 8.763-46.146.345-67.319-10.602-26.668-34.666-47.584-62.057-53.939-10.061-2.335-23.022-3.181-31.801-2.078zm22.644 65.543c9.925 4.856 14.801 13.409 14.167 24.851-.453 8.175-2.42 12.899-7.478 17.956-5.615 5.616-9.692 7.167-18.833 7.167-9.147 0-13.649-1.715-19.281-7.347-7.588-7.589-9.772-19.703-5.344-29.641 2.689-6.033 5.244-8.89 10.957-12.25 8.403-4.942 16.728-5.18 25.812-.736z'\n\nconst PopcornShare = {\n  mounted() {\n    this.game = this.el.dataset.game || 'a game'\n    this.score = this.el.dataset.score || '0'\n    this.path = this.el.dataset.path || ''\n    this.canvas = this.el.querySelector('[data-canvas]')\n    this.sheet = this.el.querySelector('[data-sheet]')\n    this.statusEl = this.el.querySelector('[data-status]')\n    this.drawn = false\n\n    this.el.querySelectorAll('[data-share]').forEach((btn) => {\n      btn.addEventListener('click', () => this.act(btn.dataset.share))\n    })\n  },\n  shareUrl() {\n    return window.location.origin + (this.path || '')\n  },\n  shareText() {\n    return `\uD83C\uDFC6 I won ${this.game} in Waiting For Popcorn! Play here: ${this.shareUrl()}`\n  },\n  status(msg) {\n    if (this.statusEl) this.statusEl.textContent = msg\n  },\n  act(action) {\n    if (action === 'open') {\n      this.draw()\n      if (this.sheet) this.sheet.classList.remove('hidden')\n      return\n    }\n    this.draw()\n    if (action === 'share') this.doShare()\n    if (action === 'copy') this.copyBoth()\n  },\n  blob() {\n    return new Promise((resolve) => this.canvas.toBlob(resolve, 'image/png'))\n  },\n  async doShare() {\n    try {\n      const blob = await this.blob()\n      const file = new File([blob], 'loor-popcorn-win.png', { type: 'image/png' })\n      if (navigator.canShare && navigator.canShare({ files: [file] })) {\n        await navigator.share({ files: [file], text: this.shareText() })\n      } else if (navigator.share) {\n        await navigator.share({ text: this.shareText(), url: this.shareUrl() })\n      } else {\n        this.copyText()\n      }\n    } catch (_e) {\n      this.status('Share cancelled.')\n    }\n  },\n  // One copy: put the image AND the link/caption on the clipboard together (like\n  // a social post), so pasting into an image field gets the card and pasting\n  // into a text field gets the link. Falls back to text-only where the platform\n  // can't hold an image on the clipboard.\n  async copyBoth() {\n    try {\n      const blob = await this.blob()\n      const text = new Blob([this.shareText()], { type: 'text/plain' })\n      await navigator.clipboard.write([\n        new window.ClipboardItem({ 'image/png': blob, 'text/plain': text }),\n      ])\n      this.status('Copied image + link \u2014 paste it anywhere!')\n    } catch (_e) {\n      try {\n        await navigator.clipboard.writeText(this.shareText())\n        this.status('Link copied (image copy not supported here) \u2014 try Share for the image.')\n      } catch (_e2) {\n        this.status(\"Couldn't copy \u2014 try Share.\")\n      }\n    }\n  },\n  draw() {\n    if (this.drawn || !this.canvas) return\n    const ctx = this.canvas.getContext('2d')\n    const W = this.canvas.width\n    const H = this.canvas.height\n    const gold = '#f5c518'\n    const cream = '#f2ede4'\n\n    const bg = ctx.createLinearGradient(0, 0, 0, H)\n    bg.addColorStop(0, '#14142a')\n    bg.addColorStop(1, '#07070f')\n    ctx.fillStyle = bg\n    ctx.fillRect(0, 0, W, H)\n\n    ctx.strokeStyle = gold\n    ctx.lineWidth = 6\n    ctx.strokeRect(12, 12, W - 24, H - 24)\n\n    ctx.textAlign = 'center'\n\n    ctx.fillStyle = cream\n    ctx.font = \"600 34px 'Bebas Neue', system-ui, sans-serif\"\n    ctx.fillText('WAITING FOR THE', W / 2, 90)\n    ctx.fillStyle = gold\n    ctx.font = \"700 58px 'Bebas Neue', system-ui, sans-serif\"\n    ctx.fillText('POPCORN \uD83C\uDF7F', W / 2, 150)\n\n    ctx.font = '150px system-ui, sans-serif'\n    ctx.fillText('\uD83C\uDFC6', W / 2, 320)\n\n    ctx.fillStyle = cream\n    ctx.font = \"700 40px 'Bebas Neue', system-ui, sans-serif\"\n    ctx.fillText('I WON', W / 2, 390)\n    ctx.fillStyle = gold\n    ctx.font = \"700 48px 'Bebas Neue', system-ui, sans-serif\"\n    ctx.fillText(this.game.toUpperCase(), W / 2, 445)\n\n    // Score \u2014 labelled, with no currency mark beside it (it's not loot).\n    ctx.fillStyle = '#9ca8b9'\n    ctx.font = \"500 28px 'Bebas Neue', system-ui, sans-serif\"\n    ctx.fillText('FINAL SCORE', W / 2, 520)\n    ctx.fillStyle = cream\n    ctx.font = \"700 110px 'Bebas Neue', system-ui, sans-serif\"\n    ctx.fillText(this.score, W / 2, 615)\n\n    // LOOR mark + wordmark as branding at the very bottom, away from the score.\n    const bs = 40 / 512\n    const markW = 403 * bs\n    ctx.textAlign = 'left'\n    ctx.font = \"600 34px 'Bebas Neue', system-ui, sans-serif\"\n    const groupW = markW + 14 + ctx.measureText('LOOR.TV').width\n    const left = W / 2 - groupW / 2\n    ctx.save()\n    ctx.translate(left, H - 66)\n    ctx.scale(bs, bs)\n    ctx.fillStyle = gold\n    ctx.fill(new Path2D(LOOT_PATH))\n    ctx.restore()\n    ctx.fillStyle = cream\n    ctx.fillText('LOOR.TV', left + markW + 14, H - 48)\n\n    this.drawn = true\n  },\n}\n\nexport default {\n  PopcornTv,\n  PopcornQr,\n  PopcornIdentity,\n  PopcornTimers,\n  PopcornClock,\n  PopcornAudio,\n  PopcornScene,\n  PopcornShare,\n}\n", "// landing.v4, \"The Fill\" (the logged-out landing page). Runs only when the\n// page root carries data-landing-design=\"fill\".\n//\n// The page has no scroll animation: it renders fully built and scrolls like\n// a plain page (scroll-linked motion made it jump and skip on older phones).\n// All that's left here is a keyboard helper for the streaming row.\nexport default function init() {\n  const root = document.querySelector('[data-landing-design=\"fill\"]')\n  if (!root) return\n\n  // Streaming row: bring each keyboard-focused card fully into view (the\n  // browser leaves a partly visible card where it is).\n  const streamViewport = root.querySelector('.fl-stream__viewport')\n  if (streamViewport) {\n    streamViewport.addEventListener('focusin', (e) => {\n      const card = e.target.closest('.fl-scard')\n      if (card) card.scrollIntoView({ block: 'nearest', inline: 'nearest' })\n    })\n  }\n}\n", "// Idle tabs let go of their live connection. Fly holds each machine to 25\n// open connections (fly.toml), and an open /show or /x tab holds one for as\n// long as it stays open. A tab hidden for 30 seconds, or left untouched for\n// 5 minutes, disconnects; coming back to it (switching to it, a tap, a key,\n// a scroll) reconnects, and the page rejoins with fresh credits and totals.\n// A tap or a form sent while it's still reconnecting is held and replayed\n// once the page is live again, so it isn't lost.\n//\n// Only on the show pages: Popcorn needs its live link, and the pitch and\n// launch forms keep theirs so nothing typed is ever at risk.\n\nconst HIDDEN_MS = 30 * 1000\nconst IDLE_MS = 5 * 60 * 1000\nconst CHECK_MS = 15 * 1000\n// How long a held tap waits for the page to come back before it's dropped.\nconst REPLAY_MS = 8 * 1000\nconst PAGES = [/^\\/show\\/[^/]+\\/?$/, /^\\/x\\/[^/]+\\/?$/]\nconst ACTIVITY = ['pointerdown', 'pointermove', 'keydown', 'wheel', 'touchstart', 'scroll', 'focusin']\n\nexport default function sleepWhenIdle(liveSocket) {\n  if (!PAGES.some((page) => page.test(location.pathname))) return null\n\n  let asleep = false\n  // Disconnecting takes a moment; a connect asked for meanwhile would be\n  // ignored, so waking waits for it to finish.\n  let closing = false\n  let wokeAt = 0\n  let lastActive = Date.now()\n  let hiddenTimer = null\n  let held = null\n\n  // The page's LiveView has joined (LiveView marks it phx-connected).\n  const live = () => !!document.querySelector('[data-phx-main].phx-connected')\n  const visible = () => document.visibilityState === 'visible'\n\n  function sleep() {\n    if (asleep || closing || !liveSocket.isConnected()) return\n    asleep = true\n    closing = true\n    liveSocket.disconnect(() => {\n      closing = false\n      if (!asleep) liveSocket.connect()\n    })\n  }\n\n  function wake() {\n    if (!asleep) return\n    asleep = false\n    wokeAt = Date.now()\n    if (!closing) liveSocket.connect()\n    // A second try if it didn't take (connect is a no-op once connected).\n    setTimeout(() => {\n      if (!asleep && !closing && !liveSocket.isConnected()) liveSocket.connect()\n    }, 3000)\n  }\n\n  // While asleep or just woken, LiveView drops events it can't send yet:\n  // hold the tap (or the form) and send it again once the page is back.\n  const catching = () => !live() && (asleep || Date.now() - wokeAt < REPLAY_MS)\n\n  function replay() {\n    const since = Date.now()\n    const tick = () => {\n      if (!held) return\n      if (live()) {\n        const { el, form } = held\n        held = null\n        if (form && form.isConnected) form.requestSubmit()\n        else if (el && el.isConnected) el.click()\n      } else if (Date.now() - since < REPLAY_MS) {\n        setTimeout(tick, 50)\n      } else {\n        held = null\n      }\n    }\n    tick()\n  }\n\n  function hold(event, target) {\n    event.preventDefault()\n    event.stopImmediatePropagation()\n    held = target\n    wake()\n    replay()\n  }\n\n  addEventListener(\n    'click',\n    (event) => {\n      if (!catching()) return\n      const el = event.target.closest && event.target.closest('[phx-click]')\n      if (el) hold(event, { el })\n    },\n    true,\n  )\n\n  addEventListener(\n    'submit',\n    (event) => {\n      if (!catching()) return\n      const form = event.target\n      if (form.matches && form.matches('[phx-submit]')) hold(event, { form })\n    },\n    true,\n  )\n\n  const active = () => {\n    lastActive = Date.now()\n    if (asleep && visible()) wake()\n  }\n  for (const type of ACTIVITY) addEventListener(type, active, { capture: true, passive: true })\n\n  document.addEventListener('visibilitychange', () => {\n    clearTimeout(hiddenTimer)\n    if (visible()) {\n      lastActive = Date.now()\n      wake()\n    } else {\n      hiddenTimer = setTimeout(sleep, HIDDEN_MS)\n    }\n  })\n\n  setInterval(() => {\n    if (visible() && Date.now() - lastActive >= IDLE_MS) sleep()\n  }, CHECK_MS)\n\n  // For checking it by hand in the console: liveSleep.sleep() / .wake().\n  return { sleep, wake, get asleep() { return asleep } }\n}\n", "// /shows in the J design (DoubloonWeb.ShowsWall, shows_j.css).\n//\n// sjPage \u2014 one component for the page, over data already on it\n// (<script id=\"sj-data\">: each tab's show names, and every show as the stage\n// shows it):\n//   * the wall: tabs, and a search over show names in the open tab;\n//   * the stage: a tapped tile's poster flies up into it and the show takes\n//     the stage. That is a history entry (?show=<slug>), so Back returns to\n//     the wall where it was. The trailer plays in the stage only when tapped:\n//     nothing previews or plays on its own (trailers stream from Vimeo, and\n//     every byte counts toward the plan's monthly threshold).\n//   * while a trailer plays under the copy (desktops and tablets, phones on\n//     their side), the copy and its glow fade out once it is moving, and\n//     come back on any mouse move, touch or key, and whenever it is paused.\n//   * the fund sheet: Produce it opens it over the page\n//     (ShowsWall.fund_sheet). A viewer with LOOT gets one slider to put it\n//     in; as on /x, the show's bar grows a striped segment out to the\n//     projected total. Everyone else gets the LOOT packs. The places come\n//     from /shows/:slug/ranks, fetched once per show: on hover or focus of\n//     the button, else on the tap.\n//   * tipping is the same sheet: on a funded show that takes tips (/show's\n//     Tip the creator) the slider and the packs work as for producing, but\n//     the LOOT goes to the creator as a tip (/shows/:slug/tip), with no place\n//     on the credits and no name for them.\n\nimport copy from 'copy-to-clipboard'\nimport Hls from 'hls.js'\nimport { clickyGoal } from './clicky_goals.js'\nimport { landed } from './loot_sheet.js'\n\nconst calm = () => window.matchMedia('(prefers-reduced-motion: reduce)').matches\n\nconst EASE = 'cubic-bezier(0.22, 1, 0.36, 1)'\n// Close enough to EASE for the scroll that runs beside the flight.\nconst easeOut = (t) => 1 - Math.pow(1 - t, 4)\nconst FLIGHT_MS = 640\n// The copy steps aside this long after the trailer starts moving, and after\n// the last mouse move or touch while it plays.\nconst IDLE_START_MS = 1200\nconst IDLE_MS = 2500\n// A tap on faded controls only brings them back (the click it makes is\n// dropped), however long the finger rests.\nconst WAKE_TAP_MS = 700\n// Where the copy sits over a playing trailer: everywhere shows_j.css sets\n// --sj-overlay: 1 (its overlay block, plus portrait tablets).\nconst OVERLAY_MQ = '(min-width: 768px), (max-height: 500px) and (orientation: landscape)'\n\n// The sheet waits this long for its place pills, so they don't pop in.\nconst RANKS_WAIT_MS = 400\n\n// Back from a purchase, the sheet reads the ledger balance this often until\n// the LOOT has been credited; slower once it's taking a while\n// (the \"Taking longer\" note shows), and slower again after a minute. It\n// never gives up while the sheet is open: a late webhook still lands.\nconst LAND_POLL_MS = 2000\nconst LAND_SLOW_MS = 20000\nconst LAND_SLOW_POLL_MS = 6000\nconst LAND_LATE_MS = 60000\nconst LAND_LATE_POLL_MS = 10000\nconst landPoll = (waited) => (waited > LAND_LATE_MS ? LAND_LATE_POLL_MS : waited > LAND_SLOW_MS ? LAND_SLOW_POLL_MS : LAND_POLL_MS)\n\n// ?err= on the way back from a checkout that didn't open (validation\n// carries the server's own &message=).\nconst CHECKOUT_ERRORS = {\n  stripe: \"Payment didn't open. Try again.\",\n  amount: 'Pick a pack and try again.',\n  email_taken: 'That email has an account. Log in.',\n  bad_login: \"That email and password don't match.\",\n  rate_limited: 'Too many tries. Wait a few minutes.',\n  expired: 'Page expired. Try again.',\n}\n\n// The \"?\" tour, one line per part of the sheet. A step whose part isn't\n// showing (no place yet, say) is skipped. `demo` slides the handle itself.\n// Membership stays out of it: the sheet is only for producing. The credit\n// credits step slides the handle too, so the name moves up as it's read.\nconst TOUR = {\n  spend: [\n    { sel: '.sjf-glass', text: 'This is LOOT, what you put into a show.', mark: true },\n    { sel: '.sjf-fund', text: 'The show fills as you slide.' },\n    { sel: '.sjf-spend .sjf-slider', text: 'Slide to choose how much.', demo: true },\n    { sel: '.sjf-crawl', text: 'The live credits. Slide more and your name moves up.', demo: true },\n    { sel: '.sjf-spend .sjf-foot', text: 'Your LOOT. Tap + for more.' },\n    { sel: '.sjf-spend .sjf-cta', text: 'Tap to produce. Your name rolls in the credits.' },\n  ],\n  buy: [\n    { sel: '.sjf-glass', text: 'This is LOOT, what you put into a show. Bigger packs add bonus LOOT.', mark: true },\n    { sel: '.sjf-buy .sjf-slider', text: 'Slide to pick a pack.', demo: true },\n    { sel: '.sjf-crawl', text: 'The live credits. Bigger packs move your name up.', demo: true },\n    { sel: '.sjf-fund', text: 'Your LOOT fills the show.' },\n    { sel: '.sjf-buy .sjf-cta', text: 'Pay securely with Stripe.' },\n  ],\n}\n\n// The \"?\" pulses for a viewer new to the sheet, until they take the tour or\n// produce something, remembered on this device. Without storage it stays\n// still rather than pulse on every visit.\nconst TOUR_SEEN = 'loor:sheet-tour-seen'\nconst tourSeen = () => {\n  try {\n    return window.localStorage.getItem(TOUR_SEEN) === '1'\n  } catch (_e) {\n    return true\n  }\n}\nconst markTourSeen = () => {\n  try {\n    window.localStorage.setItem(TOUR_SEEN, '1')\n  } catch (_e) {\n    /* private mode etc.: it just won't be remembered */\n  }\n}\n// The same tour when tipping: no credits, no fill. `plain` is the step's\n// text on a show not crowdfunded on LOOR, never \"fully funded\" here.\nconst TIP_TOUR = {\n  spend: [\n    { sel: '.sjf-glass', text: 'This is LOOT, what you tip the creator.', mark: true },\n    { sel: '.sjf-fund', text: 'Fully funded. Tips are open.', plain: 'Tips are open.' },\n    { sel: '.sjf-spend .sjf-slider', text: 'Slide to choose how much.', demo: true },\n    { sel: '.sjf-spend .sjf-foot', text: 'Your LOOT. Tap + for more.' },\n    { sel: '.sjf-spend .sjf-cta', text: 'Tap to tip the creator.' },\n  ],\n  buy: [\n    { sel: '.sjf-glass', text: 'This is LOOT, what you tip the creator. Bigger packs add bonus LOOT.', mark: true },\n    { sel: '.sjf-buy .sjf-slider', text: 'Slide to pick a pack.', demo: true },\n    { sel: '.sjf-fund', text: 'Fully funded. Tips are open.', plain: 'Tips are open.' },\n    { sel: '.sjf-buy .sjf-cta', text: 'Pay securely with Stripe.' },\n  ],\n}\n\n// Where an amount would put the viewer on the show's credits, any place\n// (/shows/:slug/ranks: every other total, biggest first, the viewer's own,\n// and the room the show has left). A pledge goes in up to that room on top\n// of what the viewer already gave; a tie ranks behind whoever got there\n// first. null without a ranking, or when the show can take no more.\nconst creditAt = (r, amount) => {\n  if (!r || !(r.room > 0)) return null\n  const total = (r.mine || 0) + Math.min(amount, r.room)\n  return 1 + (r.top || []).filter((a) => a >= total).length\n}\n\n// The places the pills and the seat badge show: the five titled seats.\nconst placeAt = (r, amount) => {\n  const place = creditAt(r, amount)\n  return place && place <= 5 ? place : null\n}\n\n// A place's credit title on the show's ladder (ShowsWall stage_ladder, as\n// Credits.Tier.tier_for/2 reads it): past the last tier's start, the last\n// tier's title.\nconst tierAt = (ladder, place) => {\n  const last = ladder[ladder.length - 1]\n  if (last && place >= last.from) return last.title\n  const tier = ladder.find((t) => place >= t.from && place <= t.to)\n  return tier ? tier.title : null\n}\n\nconst placesFor = (r, packs) => {\n  const out = {}\n  for (const p of packs) {\n    const place = placeAt(r, p.amount)\n    if (place) out[p.amount] = place\n  }\n  return out\n}\n\nconst fmt = (n) => Math.round(n || 0).toLocaleString('en-US')\n\n// \u2500\u2500 The credits crawl (ShowsWall.fund_sheet, .sjf-crawl) \u2500\u2500\n// The show's whole credits in the sheet, as film end credits: the five\n// seats, each title over its holder, then Special Thanks, with the viewer's\n// name where the slider (or the pack) puts it. The names come with the\n// show's /ranks (names lines up with top; past its first 100, \"and N\n// more\"), so it costs no request of its own. Each name is one element that\n// glides from place to place (FLIP), so it jumps a place each time it\n// passes someone, and the list scrolls to keep the viewer in view. Drawn\n// here rather than by Alpine, inside phx-update=\"ignore\", so /show's\n// LiveView leaves its rows alone.\nconst SEATS = 5\n\nconst el = (tag, cls, text) => {\n  const e = document.createElement(tag)\n  e.className = cls\n  if (text != null) e.textContent = text\n  return e\n}\n\nconst replay = (e, cls) => {\n  e.classList.remove(cls)\n  void e.offsetWidth\n  e.classList.add(cls)\n}\n\n// A place's credit title: the show's credits, else its ladder.\nconst titleAt = (show, place) => {\n  const seat = (show.credits || []).find((c) => c.rank === place)\n  return (seat && seat.role) || tierAt(show.ladder || [], place) || ''\n}\n\n// The places, one slot each: a seat for each of the five (an open seat\n// where nobody can be yet), then a line per name below, under its title\n// whenever the title changes (Special Thanks, on the default ladder). The\n// viewer makes one more name than the reply has.\nconst buildCrawl = (track, r, show) => {\n  track.textContent = ''\n  const names = r.names || []\n  const named = names.length\n  const unnamed = Math.max(0, (r.top || []).length - named)\n  const rows = named + 1\n  const slots = []\n  let last = null\n  for (let place = 1; place <= Math.max(rows, SEATS); place++) {\n    const title = titleAt(show, place)\n    const who = el('span', 'sjf-cr-who')\n    let slot\n    if (place <= SEATS) {\n      slot = el('div', 'sjf-cr-slot sjf-cr-seat')\n      slot.append(el('span', 'sjf-cr-t', title), who)\n      if (place > rows) who.append(el('span', 'sjf-cr-open', 'Open seat'))\n    } else {\n      if (title !== last) track.append(el('p', 'sjf-cr-h', title))\n      slot = el('div', 'sjf-cr-slot sjf-cr-st')\n      slot.append(who)\n    }\n    last = title\n    // Past the names the reply carries: the rest as a count, above the\n    // viewer's own line when they're among them, else below it.\n    if (unnamed && place === rows) track.append(el('p', 'sjf-cr-more sjf-cr-above'))\n    track.append(slot)\n    if (place <= rows) slots.push({ slot, who })\n  }\n  const below = unnamed ? track.appendChild(el('p', 'sjf-cr-more')) : null\n  const person = (name, you) => {\n    const p = el('span', 'sjf-cr-p' + (you ? ' is-you' : ''))\n    const pi = el('span', 'sjf-cr-pi')\n    pi.append(el('span', 'sjf-cr-nm', name))\n    p.append(pi)\n    return p\n  }\n  const people = names.map((n) => person(n))\n  const you = person('You', true)\n  return { r, show: show.id, track, slots, people, you, named, unnamed, above: track.querySelector('.sjf-cr-above'), below, place: null }\n}\n\n// Keep the viewer's line just above the middle of the window (or the\n// list centred when it all fits).\nconst viewCrawl = (c, idx, instant) => {\n  const win = c.track.parentElement\n  const s = c.slots[idx].slot\n  const H = win.clientHeight\n  const T = c.track.offsetHeight\n  const y = T <= H ? (H - T) / 2 : Math.min(0, Math.max(H - T, H * 0.46 - (s.offsetTop + s.offsetHeight / 2)))\n  if (instant) c.track.style.transition = 'none'\n  c.track.style.transform = `translateY(${y}px)`\n  if (instant) {\n    void c.track.offsetWidth\n    c.track.style.transition = ''\n  }\n}\n\n// Put the viewer at `place` (1 is the top of the credits) under `name`.\n// When the place changes, every name glides from where it is on screen to\n// its new line: measure, move, invert, then let the transition run.\nconst drawCrawl = (c, place, name, instant) => {\n  const youName = c.you.querySelector('.sjf-cr-nm')\n  if (youName.textContent !== name) youName.textContent = name\n  if (place === c.place && !instant) return\n  const idx = Math.min(place - 1, c.named)\n  const order = [...c.people]\n  order.splice(idx, 0, c.you)\n  const all = [...c.people, c.you]\n  const first = new Map(all.map((p) => [p, p.parentNode ? p.getBoundingClientRect() : null]))\n  order.forEach((p, i) => {\n    if (p.parentNode !== c.slots[i].who) c.slots[i].who.append(p)\n  })\n  c.slots.forEach((s, i) => s.slot.classList.toggle('has-you', i === idx))\n  if (c.unnamed) {\n    const ahead = Math.max(0, place - 1 - c.named)\n    c.above.textContent = ahead ? `and ${fmt(ahead)} more` : ''\n    c.above.hidden = !ahead\n    c.below.textContent = c.unnamed - ahead ? `and ${fmt(c.unnamed - ahead)} more` : ''\n    c.below.hidden = !(c.unnamed - ahead)\n  }\n  for (const p of all) {\n    p.style.transition = 'none'\n    p.style.transform = 'none'\n  }\n  if (!instant && !calm()) {\n    for (const p of all) {\n      const f = first.get(p)\n      if (!f) continue\n      const l = p.getBoundingClientRect()\n      const dx = f.left - l.left\n      const dy = f.top - l.top\n      if (Math.abs(dx) > 0.5 || Math.abs(dy) > 0.5) p.style.transform = `translate(${dx}px, ${dy}px)`\n    }\n  }\n  viewCrawl(c, idx, instant || calm())\n  void c.track.offsetWidth\n  for (const p of all) {\n    p.style.transition = ''\n    p.style.transform = ''\n  }\n  // Up a place: the name pops, the one it passed dips, a seat's title glows.\n  if (!instant && c.place && place < c.place) {\n    replay(c.you, 'is-pop')\n    if (order[idx + 1]) replay(order[idx + 1], 'is-bump')\n    if (place <= SEATS) replay(c.slots[idx].slot, 'is-take')\n  }\n  c.place = place\n}\n\n// The header's LOOT pill (layout_view.ex) after a spend, from the ledger\n// figures /produce and /tip answer with: gold, and a member's silver beside\n// it, hidden at 0 as the server renders it. Plain numbers, as rendered.\nconst headerLoot = (r) => {\n  if (typeof r.gold === 'number') {\n    for (const el of document.querySelectorAll('[data-loot-gold]')) el.textContent = String(r.gold)\n  }\n  if (typeof r.silver === 'number') {\n    for (const el of document.querySelectorAll('[data-loot-silver]')) {\n      const n = el.querySelector('[data-loot-n]')\n      if (n) n.textContent = String(r.silver)\n      el.hidden = r.silver <= 0\n    }\n  }\n}\n\nconst csrf = () => {\n  const meta = document.querySelector('meta[name=\"csrf-token\"]')\n  return meta ? meta.content : ''\n}\n\nconst instantScroll = (y) => window.scrollTo({ top: y, left: 0, behavior: 'instant' })\n\nconst readData = () => {\n  const el = document.getElementById('sj-data')\n  try {\n    return el ? JSON.parse(el.textContent) : {}\n  } catch (_e) {\n    return {}\n  }\n}\n\nexport default ({ tab, scroll, home, show, picked, balance = 0, named = false, member = false }) => {\n  const data = readData()\n  const names = data.names || {}\n  const byId = new Map((data.catalog || []).map((p) => [p.id, p]))\n  const packs = data.packs || []\n  // The pack the sheet opens on: Produce's (rec), or Tip's (rec_tip).\n  const recIdx = Math.max(0, packs.findIndex((p) => p.rec))\n  const tipIdx = packs.some((p) => p.rec_tip) ? packs.findIndex((p) => p.rec_tip) : recIdx\n  // slug -> a promise of its /ranks reply (null when it failed)\n  const ranks = new Map()\n  const blank = { id: null, name: '', href: '#', state: 'watch' }\n  // Page-scoped handles that Alpine needn't watch.\n  const dom = {\n    stage: null,\n    layers: [],\n    layer: 0,\n    posterTok: 0,\n    copyT: null,\n    rollT: null,\n    idleT: null,\n    hold: false,\n    wakeTap: 0,\n    hls: null,\n    src: null,\n    fromTile: null,\n    fundFrom: null,\n    countTok: 0,\n    // the purchase-landing loop running (a reopened sheet starts a new one)\n    landTok: 0,\n    demoT: null,\n    demoFrom: null,\n    // the credits crawl drawn for the open sheet (buildCrawl), and the\n    // ResizeObserver that keeps the viewer's line in view\n    crawl: null,\n    crawlFit: null,\n    // when the share button stops saying \"Link copied\"\n    copiedT: null,\n  }\n  // The copy sits over the trailer from tablet size up and on phones on\n  // their side (shows_j.css sets --sj-overlay there); on a phone held\n  // upright it sits below it.\n  const overlaid = () => !!dom.stage && getComputedStyle(dom.stage).getPropertyValue('--sj-overlay').trim() === '1'\n\n  return {\n    tab,\n    q: '',\n    showId: show,\n    picked,\n    copyOut: false,\n    announce: '',\n    // trailer: on (playing or paused in the stage), its frames showing,\n    // paused, sound off, how far through (0..1), and the copy stepped aside\n    trailer: false,\n    rolling: false,\n    failed: false,\n    paused: false,\n    muted: false,\n    progress: 0,\n    idle: false,\n    // the fund sheet: open, tipping rather than producing, the pack picked,\n    // places by pack amount\n    fund: false,\n    tipping: false,\n    fundSel: recIdx,\n    places: {},\n    // spending: 'spend' (the slider) or 'buy' (the packs); the viewer's\n    // balance; the amount on the slider; the show's /ranks reply; a pledge\n    // in flight, its error, its result; the credit name to save with it\n    mode: 'buy',\n    balance,\n    named,\n    amount: 0,\n    rank: null,\n    busy: false,\n    error: '',\n    done: null,\n    creditName: '',\n    // produced: the show's link was just copied (the button says so)\n    copied: false,\n    // bumped when a pledge moves a show's numbers (the catalog isn't reactive)\n    rev: 0,\n    // the spend slider not yet touched (the balance stays whole and the\n    // handle nudges until it is); the \"?\" tour's step (-1: off) and where\n    // its spotlight and card sit; whether the \"?\" pulses (new here)\n    touched: false,\n    helpNew: !tourSeen(),\n    tour: -1,\n    tourList: null,\n    tourHole: '',\n    tourCard: '',\n    // the buy pill's numbers as they count up to the picked pack (its LOOT,\n    // and how much more LOOT its bonus gives, in percent), and the bonus\n    // chip's pop\n    tick: { loot: 0, more: 0, pop: false },\n    // back from a purchase: waiting for it to land ({ paid, want, slow }),\n    // what landed (shown by the balance until the slider moves), and the\n    // balance as it counts up (null: not counting)\n    landing: null,\n    landed: 0,\n    rise: null,\n    // buying signed out: the account fields open under the pack (signup),\n    // making one or logging in (account), and what was typed; the Every\n    // show switch (join) for a viewer without a membership (member)\n    member,\n    signup: false,\n    account: 'register',\n    typed: { credit_name: '', email: '' },\n    join: false,\n    // the checkout form on its way (a second tap opens no second Checkout)\n    sending: false,\n\n    get cur() {\n      void this.rev\n      return byId.get(this.showId) || blank\n    },\n\n    // \u2500\u2500 wall: tabs and search \u2500\u2500\n\n    get needle() {\n      return this.q.trim().toLowerCase()\n    },\n    hit(name) {\n      return !this.needle || name.includes(this.needle)\n    },\n    hits(key) {\n      return (names[key] || []).filter((n) => this.hit(n)).length\n    },\n    find() {\n      this.$refs.q.focus({ preventScroll: true })\n      this.$refs.wall.scrollIntoView({ behavior: calm() ? 'auto' : 'smooth' })\n    },\n\n    init() {\n      const stage = document.getElementById('sj-stage')\n      dom.stage = stage\n      if (stage) {\n        dom.layers = [...stage.querySelectorAll('.sj-poster')]\n        // The copy's height sizes the scrim behind it and, on a phone, where\n        // the trailer sits above it.\n        const copy = stage.querySelector('.sj-copy')\n        if (copy) {\n          const measure = () => stage.style.setProperty('--sj-copy-h', copy.offsetHeight + 'px')\n          measure()\n          if ('ResizeObserver' in window) new ResizeObserver(measure).observe(copy)\n        }\n        // The poster stays up until the trailer is actually moving, not\n        // while it seeks and buffers.\n        const video = this.$refs.video\n        video.addEventListener('timeupdate', () => {\n          if (!this.trailer) return\n          if (!this.rolling && video.currentTime > 0.15) this.rolling = true\n          this.progress = video.duration ? Math.min(1, video.currentTime / video.duration) : 0\n        })\n        video.addEventListener('canplay', () => {\n          // Play with sound refused: show the paused first frame and Play.\n          setTimeout(() => {\n            if (this.trailer && !this.rolling && video.paused) this.rolling = true\n          }, 1500)\n        })\n        video.addEventListener('playing', () => {\n          if (!this.trailer) return\n          this.paused = false\n          this.armIdle(IDLE_START_MS)\n        })\n        video.addEventListener('pause', () => {\n          if (!this.trailer) return\n          this.paused = true\n          this.wake()\n        })\n        video.addEventListener('volumechange', () => (this.muted = video.muted))\n        video.addEventListener('ended', () => this.stop())\n        video.addEventListener('error', () => {\n          if (this.trailer) this.fail()\n        })\n        // A phone turned on its side mid-trailer: the copy now sits over the\n        // picture, so start the fade (and turned back, bring it back).\n        const mq = window.matchMedia(OVERLAY_MQ)\n        const turned = () => this.wake()\n        if (mq.addEventListener) mq.addEventListener('change', turned)\n        else if (mq.addListener) mq.addListener(turned)\n      }\n\n      window.addEventListener('popstate', (e) => this.onPop(e.state || {}))\n      // Back from Stripe to a page kept whole: the form can go again.\n      window.addEventListener('pageshow', (e) => e.persisted && (this.sending = false))\n      // A new pack, or the packs coming into view: count up to it.\n      this.$watch('fundSel', () => this.countTo())\n      this.$watch('mode', (m) => m === 'buy' && this.countTo(true))\n      // A ?show= page opened cold: mark the entry so Back to the wall\n      // restores in place rather than leaving the page.\n      if (this.picked) {\n        try {\n          history.replaceState(Object.assign({}, history.state, { sjShow: this.showId }), '')\n        } catch (_e) {}\n      } else if (scroll) {\n        this.$nextTick(() => this.$refs.wall.scrollIntoView())\n      }\n      // Back from a checkout. Paid (?paid=<LOOT>&pre=<balance before>): the\n      // sheet opens on the slider and waits for the LOOT to land. Left\n      // unpaid, or it didn't open (?fund=buy, maybe &err=): on the packs.\n      const qs = new URLSearchParams(location.search)\n      const paid = parseInt(qs.get('paid'), 10)\n      const pre = parseInt(qs.get('pre'), 10)\n      // The purchase itself (its Checkout Session, from /loot/return).\n      const lp = qs.get('lp')\n      const errKey = qs.get('err')\n      const err = errKey === 'validation' ? qs.get('message') || '' : CHECKOUT_ERRORS[errKey] || ''\n      if (qs.has('fund') || paid > 0) {\n        const mode = paid > 0 ? 'spend' : qs.get('fund') === 'buy' ? 'buy' : null\n        // The packs as they were left: the pack, the switch, what was typed.\n        const back = {\n          amount: parseInt(qs.get('amount'), 10),\n          join: qs.get('member') === '1',\n          account: qs.get('mode') === 'login' ? 'login' : 'register',\n          typed: { credit_name: qs.get('credit_name') || '', email: qs.get('email') || '' },\n        }\n        const keys = ['fund', 'paid', 'pre', 'lp', 'err', 'message', 'amount', 'member', 'mode', 'credit_name', 'email']\n        for (const k of keys) qs.delete(k)\n        const rest = qs.toString()\n        try {\n          history.replaceState(history.state, '', location.pathname + (rest ? '?' + rest : '') + location.hash)\n        } catch (_e) {}\n        if (paid > 0) {\n          // The balance shown starts from before the purchase and counts up.\n          const before = pre >= 0 ? pre : 0\n          this.landing = { paid, lp, want: before + paid, slow: false, t0: Date.now() }\n          this.balance = before\n        }\n        this.openFund({ mode }).then(() => {\n          // The show stopped taking LOOT meanwhile: no sheet, nothing to wait on.\n          if (!this.fund) return (this.landing = null)\n          if (mode === 'buy') {\n            const k = packs.findIndex((p) => p.amount === back.amount)\n            if (k >= 0) this.fundSel = k\n            this.join = back.join\n            this.account = back.account\n            this.typed = back.typed\n            // Something to fix in the account: the fields open again.\n            if (back.typed.email || (errKey && errKey !== 'stripe' && errKey !== 'amount')) this.signup = true\n          }\n          this.error = err\n        })\n      }\n    },\n\n    // \u2500\u2500 wall \u2192 stage \u2500\u2500\n\n    tap(e) {\n      const a = e.target.closest && e.target.closest('a.sj-tile[data-id]')\n      if (!a || !document.getElementById('sj-stage')) return\n      // A new tab, a new window, a download: the link does its job.\n      if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || (e.button && e.button !== 0)) return\n      const id = Number(a.dataset.id)\n      if (!byId.has(id)) return\n      e.preventDefault()\n      this.pick(id, a)\n    },\n\n    pick(id, tile) {\n      const p = byId.get(id)\n      const vessel = tile && tile.querySelector('.sj-vessel')\n      const y0 = window.scrollY\n      this.stop()\n      this.picked = true\n      this.announce = p.name\n      dom.fromTile = tile || null\n      // This entry remembers where the wall was; the new one carries the show.\n      try {\n        history.replaceState(Object.assign({}, history.state, { sjY: y0, sjTile: id }), '')\n        const url = new URL(window.location.href)\n        url.searchParams.set('show', p.slug)\n        history.pushState({ sjShow: id, sjPushed: true }, '', url)\n      } catch (_e) {\n        /* history unavailable: the chip still restores in place */\n      }\n      const media = document.querySelector('#sj-stage .sj-media')\n      if (!vessel || !media || calm()) {\n        this.present(id, 0)\n        instantScroll(0)\n        this.focusTitle()\n        return\n      }\n      // The poster lifts off the wall and grows into the stage while the\n      // page scrolls up under it; the stage swaps underneath, then the\n      // flying copy fades into it.\n      const from = vessel.getBoundingClientRect()\n      const m = media.getBoundingClientRect()\n      const to = { left: m.left, top: m.top + y0, width: m.width, height: m.height }\n      // Where the stage shows the whole cover (--sj-whole), land on the\n      // cover: 16:9 at the stage's height, centred.\n      if (getComputedStyle(dom.stage).getPropertyValue('--sj-whole').trim() === '1') {\n        const w = Math.min(m.width, (m.height * 16) / 9)\n        Object.assign(to, { left: m.left + (m.width - w) / 2, width: w })\n      }\n      const src = vessel.querySelector('img')\n      const fly = document.createElement('div')\n      fly.className = 'sj-flight'\n      fly.setAttribute('aria-hidden', 'true')\n      const fi = document.createElement('img')\n      fi.alt = ''\n      fi.src = (src && (src.currentSrc || src.src)) || p.cover || p.portrait || ''\n      fly.appendChild(fi)\n      Object.assign(fly.style, { left: from.left + 'px', top: from.top + 'px', width: from.width + 'px', height: from.height + 'px' })\n      document.body.appendChild(fly)\n      tile.classList.add('is-lifted')\n\n      const poster = this.present(id, FLIGHT_MS - 180)\n      fly.animate(\n        [\n          { left: from.left + 'px', top: from.top + 'px', width: from.width + 'px', height: from.height + 'px', borderRadius: '12px' },\n          { left: to.left + 'px', top: to.top + 'px', width: to.width + 'px', height: to.height + 'px', borderRadius: '0px' },\n        ],\n        { duration: FLIGHT_MS, easing: EASE, fill: 'forwards' }\n      )\n      fi.animate([{ objectPosition: '50% 50%' }, { objectPosition: window.innerWidth < 768 ? '50% 20%' : '50% 50%' }], {\n        duration: FLIGHT_MS,\n        easing: EASE,\n        fill: 'forwards',\n      })\n\n      const t0 = performance.now()\n      const step = (now) => {\n        const t = Math.min(1, (now - t0) / FLIGHT_MS)\n        instantScroll(Math.round(y0 * (1 - easeOut(t))))\n        if (t < 1) requestAnimationFrame(step)\n      }\n      requestAnimationFrame(step)\n\n      const land = () => {\n        tile.classList.remove('is-lifted')\n        const out = fly.animate([{ opacity: 1 }, { opacity: 0 }], { duration: 280, easing: 'ease-out', fill: 'forwards' })\n        out.onfinish = () => fly.remove()\n        this.focusTitle()\n      }\n      const timeout = new Promise((r) => setTimeout(r, FLIGHT_MS + 500))\n      setTimeout(() => Promise.race([poster, timeout]).then(land), FLIGHT_MS)\n    },\n\n    // Put a show on the stage: poster now, copy after a short fade.\n    present(id, delay = 170) {\n      const p = byId.get(id)\n      if (!p) return Promise.resolve()\n      const poster = this.setPoster(p)\n      clearTimeout(dom.copyT)\n      if (id === this.showId || calm() || delay === 0) {\n        this.showId = id\n        this.copyOut = false\n        return poster\n      }\n      this.copyOut = true\n      dom.copyT = setTimeout(() => {\n        this.showId = id\n        this.copyOut = false\n      }, delay)\n      return poster\n    },\n\n    // Swap the stage poster: load into the hidden layer, crossfade when ready.\n    setPoster(p) {\n      const layers = dom.layers\n      if (!layers.length) return Promise.resolve()\n      const on = layers[dom.layer]\n      if (on.dataset.pid === String(p.id)) return Promise.resolve()\n      const next = layers[1 - dom.layer]\n      const source = next.querySelector('source')\n      const img = next.querySelector('img')\n      if (source) source.srcset = p.portrait || p.cover || ''\n      img.src = p.cover || p.portrait || ''\n      next.style.setProperty('--sj-art', p.cover ? `url(\"${p.cover.replace(/\"/g, '%22')}\")` : 'none')\n      next.dataset.pid = String(p.id)\n      const tok = ++dom.posterTok\n      const show = () => {\n        if (tok !== dom.posterTok) return\n        on.classList.remove('is-on')\n        next.classList.add('is-on')\n        dom.layer = 1 - dom.layer\n      }\n      const ready = img.decode ? img.decode().catch(() => {}) : Promise.resolve()\n      return ready.then(show)\n    },\n\n    // The stage chip. A pick made on this page is a history entry, so this\n    // is the browser's Back (popstate does the rest); a ?show= link opened\n    // cold has nothing behind it, so restore in place.\n    backToWall() {\n      const s = history.state || {}\n      if (s.sjPushed) {\n        history.back()\n        return\n      }\n      const id = this.showId\n      this.unpick()\n      try {\n        const url = new URL(window.location.href)\n        url.searchParams.delete('show')\n        history.replaceState(Object.assign({}, s, { sjShow: null }), '', url)\n      } catch (_e) {}\n      const tile = this.tileFor(id)\n      const y = tile ? tile.getBoundingClientRect().top + window.scrollY - window.innerHeight / 3 : this.wallTop()\n      instantScroll(Math.max(0, Math.round(y)))\n      if (tile) tile.focus({ preventScroll: true })\n    },\n\n    unpick() {\n      this.stop()\n      this.picked = false\n      if (home !== null) this.present(home, 0)\n    },\n\n    // Back / Forward between the wall and a picked show.\n    onPop(s) {\n      this.closeFund()\n      if (s.sjShow != null && byId.has(s.sjShow)) {\n        this.stop()\n        this.picked = true\n        this.present(s.sjShow, 0)\n        this.focusTitle()\n      } else if (this.picked) {\n        this.unpick()\n      }\n      if (typeof s.sjY === 'number') {\n        const y = s.sjY\n        instantScroll(y)\n        // (the browser may restore its own scroll right after popstate)\n        requestAnimationFrame(() => instantScroll(y))\n        const tile = this.tileFor(s.sjTile)\n        if (tile) tile.focus({ preventScroll: true })\n      }\n    },\n\n    // The tile a show was picked from, or its visible twin on the wall.\n    tileFor(id) {\n      const t = dom.fromTile\n      if (t && document.contains(t) && t.offsetParent !== null && Number(t.dataset.id) === id) return t\n      const all = [...this.$root.querySelectorAll(`a.sj-tile[data-id=\"${id}\"]`)]\n      return all.find((a) => a.offsetParent !== null) || null\n    },\n\n    wallTop() {\n      return Math.max(0, Math.round(this.$refs.wall.getBoundingClientRect().top + window.scrollY))\n    },\n\n    focusTitle() {\n      const a = document.querySelector('#sj-stage .sj-title a')\n      if (a) a.focus({ preventScroll: true })\n    },\n\n    // \u2500\u2500 trailer: only ever on a tap \u2500\u2500\n\n    // From the top, with sound, at the quality the player's size calls for.\n    // The page draws its own controls (Pause, Sound, Close), so the copy can\n    // step aside without the browser's bar sitting on the picture.\n    watch() {\n      const src = this.cur.trailer\n      const video = this.$refs.video\n      if (!src || !video) return\n      if (dom.src !== src) {\n        this.unload()\n        dom.src = src\n        if (Hls.isSupported() && /\\.m3u8/.test(src)) {\n          dom.hls = new Hls({ capLevelToPlayerSize: true })\n          dom.hls.on(Hls.Events.ERROR, (_e, d) => {\n            if (d.fatal) this.fail()\n          })\n          dom.hls.loadSource(src)\n          dom.hls.attachMedia(video)\n        } else {\n          video.src = src\n        }\n      } else if (dom.hls) {\n        dom.hls.startLoad()\n      }\n      this.failed = false\n      this.rolling = false\n      this.paused = false\n      this.progress = 0\n      this.idle = false\n      this.trailer = true\n      clearTimeout(dom.rollT)\n      dom.rollT = setTimeout(() => (this.rolling = true), 8000)\n      video.controls = false\n      video.muted = false\n      video.currentTime = 0\n      video.play().catch(() => (this.paused = true))\n    },\n\n    // Won't play: the copy stays up and the button offers Play, not Pause.\n    fail() {\n      this.failed = true\n      this.paused = true\n      this.idle = false\n      clearTimeout(dom.idleT)\n    },\n\n    // The art (anywhere off the copy) and the Pause / Play button.\n    togglePlay() {\n      const video = this.$refs.video\n      if (!video) return\n      if (video.paused) video.play().catch(() => (this.paused = true))\n      else video.pause()\n    },\n\n    toggleMute() {\n      const video = this.$refs.video\n      if (video) video.muted = !video.muted\n    },\n\n    // Close the trailer: pause, stop downloading, and the poster and copy\n    // come back.\n    stop() {\n      const video = this.$refs.video\n      // Close trailer or Sound had focus: both go away with the trailer, so\n      // hand focus to the Trailer button rather than drop it on the page.\n      const row = dom.stage && dom.stage.querySelector('.sj-toprow')\n      const orphan = this.trailer && row && row.contains(document.activeElement)\n      clearTimeout(dom.rollT)\n      clearTimeout(dom.idleT)\n      if (video) video.pause()\n      if (dom.hls) dom.hls.stopLoad()\n      this.trailer = false\n      this.rolling = false\n      this.paused = false\n      this.progress = 0\n      this.idle = false\n      if (orphan)\n        this.$nextTick(() => {\n          const b = dom.stage.querySelector('.sj-ctas .sj-btn--ghost')\n          if (b && (!document.activeElement || document.activeElement === document.body)) b.focus({ preventScroll: true })\n        })\n    },\n\n    // \u2500\u2500 the copy over a playing trailer \u2500\u2500\n\n    // Any mouse move, touch or key brings the copy back; while the trailer\n    // plays it steps aside again after a pause in activity.\n    wake() {\n      this.idle = false\n      if (this.trailer && !this.paused) this.armIdle(IDLE_MS)\n      else clearTimeout(dom.idleT)\n    },\n\n    // Only once the trailer is really moving: not while it loads, stalls,\n    // or has failed.\n    armIdle(ms) {\n      clearTimeout(dom.idleT)\n      if (!overlaid()) return\n      dom.idleT = setTimeout(() => {\n        const v = this.$refs.video\n        const moving = v && !v.paused && v.readyState >= 3\n        if (this.trailer && moving && !this.paused && !this.failed && !dom.hold && !this.keyboardIn()) this.idle = true\n      }, ms)\n    },\n\n    // A touch on faded controls wakes them; the tap's click is dropped so it\n    // can't press a control the finger couldn't see.\n    touchWake() {\n      dom.wakeTap = this.idle ? performance.now() : 0\n      this.wake()\n    },\n\n    eatWakeTap(e) {\n      const t = dom.wakeTap\n      dom.wakeTap = 0\n      if (t && performance.now() - t < WAKE_TAP_MS) {\n        e.preventDefault()\n        e.stopPropagation()\n      }\n    },\n\n    // The pointer resting on the copy or the top row keeps them up.\n    hold(on) {\n      dom.hold = on\n      if (!on) this.wake()\n    },\n\n    // The pointer left the stage: let the copy go sooner.\n    leave() {\n      dom.hold = false\n      if (this.trailer && !this.paused) this.armIdle(600)\n    },\n\n    // A keyboard user working the controls keeps them on screen.\n    keyboardIn() {\n      const el = document.activeElement\n      return !!(el && dom.stage && dom.stage.contains(el) && el.matches(':focus-visible'))\n    },\n\n    unload() {\n      const video = this.$refs.video\n      if (dom.hls) {\n        dom.hls.destroy()\n        dom.hls = null\n      }\n      if (video) {\n        video.removeAttribute('src')\n        video.load()\n      }\n      dom.src = null\n    },\n\n    // \u2500\u2500 the fund sheet \u2500\u2500\n\n    pack() {\n      return packs[this.fundSel] || { amount: 0, price: '', label: '', g: 0 }\n    },\n    get packCount() {\n      return packs.length\n    },\n    // Where the picked pack sits on the pack scrubber (smallest left), 0..100.\n    packAt() {\n      return packs.length > 1 ? ((packs.length - 1 - this.fundSel) / (packs.length - 1)) * 100 : 100\n    },\n    // What rides on the glass: the LOOT going in, and the place it earns.\n    shown() {\n      if (this.done) return this.done.spent\n      if (this.landing) return this.landing.paid\n      return this.mode === 'spend' ? this.amount : this.tick.loot\n    },\n    // The buy pill counts up (or down) to the picked pack's LOOT and bonus,\n    // so the bonus visibly grows as the slider climbs. `now` jumps there.\n    countTo(now = false) {\n      const p = this.pack()\n      const from = { loot: this.tick.loot, more: this.tick.more }\n      const tok = ++dom.countTok\n      if ((p.more || 0) > from.more && !now) {\n        this.tick.pop = true\n        setTimeout(() => tok === dom.countTok && (this.tick.pop = false), 180)\n      }\n      const ms = now || calm() ? 0 : 450\n      const t0 = performance.now()\n      const step = (t) => {\n        if (tok !== dom.countTok) return\n        const k = ms ? Math.min(1, (t - t0) / ms) : 1\n        const e = 1 - Math.pow(1 - k, 3)\n        this.tick.loot = from.loot + (p.amount - from.loot) * e\n        this.tick.more = from.more + ((p.more || 0) - from.more) * e\n        if (k < 1) requestAnimationFrame(step)\n      }\n      ms ? requestAnimationFrame(step) : step(t0)\n    },\n    place() {\n      if (this.done) return this.done.place\n      if (this.tipping) return null\n      return this.mode === 'spend' ? this.placeNow() : this.places[this.pack().amount] || null\n    },\n    // Done: what the confirmation says over its share. Produced into a\n    // place: \"You're in the credits\" over \"#2\" and the show's credit title\n    // for it (Special Thanks past the seats). Tipped: \"Thanks for the tip\"\n    // over the LOOT.\n    won() {\n      const d = this.done\n      if (!d) return { kicker: '', n: '', title: '' }\n      if (this.tipping) return { kicker: 'Thanks for the tip', n: '', title: `${fmt(d.spent)} LOOT` }\n      if (!d.place) return { kicker: \"You're producing it\", n: '', title: this.cur.name }\n      return { kicker: \"You're in the credits\", n: `#${d.place}`, title: titleAt(this.cur, d.place) }\n    },\n    shareLine() {\n      return this.tipping ? `Tell your friends about ${this.cur.name}.` : `Tell your friends you're producing ${this.cur.name}.`\n    },\n    // Done: the show's own link onto the clipboard, to tell people (it\n    // unfurls with the show's share card), and the button says it's copied\n    // once it is. The browser's clipboard first; the old copy as a fallback.\n    async copyShow() {\n      const url = new URL(this.cur.href, window.location.origin).href\n      let ok = false\n      try {\n        await navigator.clipboard.writeText(url)\n        ok = true\n      } catch (_e) {\n        try {\n          ok = copy(url)\n        } catch (_e2) {\n          ok = false\n        }\n      }\n      if (!ok) return\n      this.copied = true\n      clearTimeout(dom.copiedT)\n      dom.copiedT = setTimeout(() => (this.copied = false), 2400)\n    },\n    // The credits crawl (ShowsWall .sjf-crawl), producing a show with\n    // credits on LOOR that can still take a pledge: never on a tip.\n    crawlOn() {\n      const c = this.cur\n      if (!this.fund || this.tipping) return false\n      if (c.crowdfunded === false || c.state !== 'fund' || c.closed || !(c.ladder || []).length) return false\n      return !(this.rank && !(this.rank.room > 0))\n    },\n    // The LOOT the crawl places the viewer by: the slider's, or the whole\n    // pack picked (as if it all went into this show).\n    crawlAmount() {\n      return this.mode === 'spend' ? this.amount : this.pack().amount\n    },\n    // The viewer's line: the credit name being typed, else their own, else\n    // \"You\" (signed out, or no credit name yet).\n    crawlName() {\n      const typed = (this.creditName || this.typed.credit_name || '').trim()\n      return typed || (this.named && this.rank && this.rank.you) || 'You'\n    },\n    // Keeps the crawl on the viewer's place as the slider, the pack, the\n    // name or the ranking change (x-effect). Drawn after Alpine shows it,\n    // so it can be measured; rebuilt for a new ranking or show.\n    crawlSync() {\n      const on = this.crawlOn()\n      const r = this.rank\n      const show = this.cur\n      const place = r && creditAt(r, this.crawlAmount())\n      const name = this.crawlName()\n      const track = this.$refs.crawl\n      if (!on || !place || !track) return\n      this.$nextTick(() => {\n        let fresh = false\n        if (!dom.crawl || dom.crawl.r !== r || dom.crawl.show !== show.id || dom.crawl.track !== track) {\n          dom.crawl = buildCrawl(track, r, show)\n          fresh = true\n        }\n        drawCrawl(dom.crawl, place, name, fresh)\n        // The window settles after it's drawn (the sheet opening, the\n        // more-LOOT note coming and going, a turned phone): keep the\n        // viewer's line in view whenever it or the list changes size.\n        if (fresh && window.ResizeObserver) {\n          if (dom.crawlFit) dom.crawlFit.disconnect()\n          const c = dom.crawl\n          dom.crawlFit = new ResizeObserver(() => c.place && viewCrawl(c, Math.min(c.place - 1, c.named), true))\n          dom.crawlFit.observe(track.parentElement)\n          dom.crawlFit.observe(track)\n        }\n      })\n    },\n    // Over the slider: the first seat the LOOT in reach can't take, and\n    // what it takes. Spending, \"in reach\" is the balance (and the show's\n    // room); buying, the biggest pack. It shows from the start when no seat\n    // is in reach, else once the slider (or the pack) is at the end. null\n    // otherwise, and on a tip, once it's in, or when the show can't take\n    // that much.\n    need() {\n      const r = this.rank\n      if (!r || !(r.room > 0) || this.tipping || this.done || !this.crawlOn()) return null\n      const spend = this.mode === 'spend'\n      if (spend ? this.landing : this.signup) return null\n      const most = spend ? this.maxAmt() : Math.max(0, ...packs.map((p) => p.amount))\n      const reach = creditAt(r, most)\n      const goal = reach > SEATS ? SEATS : reach - 1\n      const above = goal >= 1 ? (r.top || [])[goal - 1] : null\n      if (above == null) return null\n      const step = spend ? this.minAmt() : 1\n      const total = Math.ceil((above + 1 - (r.mine || 0)) / step) * step\n      if (total > r.room) return null\n      const atEnd = spend ? this.amount >= most : this.pack().amount >= most\n      if (reach <= SEATS && !atEnd) return null\n      return { title: titleAt(this.cur, goal), total, more: Math.max(0, total - (spend ? this.balance : 0)) }\n    },\n    needOn() {\n      return !!this.need()\n    },\n    // \"19,900 more LOOT\" while spending; \"22,900 LOOT\" while buying.\n    needLine() {\n      const n = this.need()\n      if (!n) return ''\n      return this.mode === 'spend' ? `${fmt(n.more)} more LOOT` : `${fmt(n.total)} LOOT`\n    },\n    loadRanks(slug) {\n      if (!slug) return Promise.resolve(null)\n      if (!ranks.has(slug)) {\n        const got = fetch(`/shows/${encodeURIComponent(slug)}/ranks`, { credentials: 'same-origin' })\n          .then((r) => (r.ok ? r.json() : null))\n          .catch(() => null)\n          .then((r) => {\n            // A failed read is tried again next time.\n            if (!r) ranks.delete(slug)\n            return r\n          })\n        ranks.set(slug, got)\n      }\n      return ranks.get(slug)\n    },\n    // `mode` opens on the slider or the packs regardless of the balance.\n    // `tip` says whether it opens to tip (the page's button knows, even when\n    // the show filled its goal after the page loaded); otherwise the show's\n    // state does.\n    async openFund({ mode, tip } = {}) {\n      const show = this.cur\n      const tipping = tip == null ? show.state === 'tip' : !!tip\n      if (!(tipping || (show.state === 'fund' && !show.closed)) || this.fund) return\n      this.tipping = tipping\n      if (this.trailer && !this.paused) this.$refs.video.pause()\n      dom.fundFrom = document.activeElement\n      this.fundSel = tipping ? tipIdx : recIdx\n      this.countTo(true)\n      this.places = {}\n      this.rank = null\n      // A purchase still landing opens on it, never on the packs again.\n      this.mode = mode || (this.landing || this.balance > 0 ? 'spend' : 'buy')\n      this.signup = false\n      if (!this.landing) this.landed = 0\n      this.rise = null\n      this.endTour()\n      // Start at 100, ready to produce; nothing comes off the balance shown\n      // until the slider is touched.\n      this.touched = false\n      this.amount = this.minAmt()\n      this.error = ''\n      this.done = null\n      this.copied = false\n      const got = this.loadRanks(show.slug).then((r) => {\n        if (this.cur.id !== show.id) return\n        this.places = placesFor(r, packs)\n        this.rank = r\n        // The ledger's figure, read as the sheet opens (the page's is a\n        // display copy that can lag). A landing purchase counts up to it.\n        // (Not once a purchase has landed: this read may predate its credit.)\n        if (r && typeof r.balance === 'number' && !this.landing && !this.landed) this.balance = r.balance\n        this.amount = Math.max(Math.min(this.amount, this.maxAmt()), this.minAmt())\n      })\n      await Promise.race([got, new Promise((done) => setTimeout(done, RANKS_WAIT_MS))])\n      if (this.cur.id !== show.id || this.fund) return\n      this.fund = true\n      document.documentElement.classList.add('sjf-lock')\n      this.$nextTick(() => this.focusControl())\n      if (this.landing) this.awaitLoot()\n    },\n    // Waiting for a purchase to land: until /loot/balance says this purchase\n    // (lp) is credited, whatever else the balance did meanwhile (a spend, a\n    // claim, silver expiring); without lp, until the balance (silver and\n    // gold, from the ledger alone) holds what was bought. Usually the first\n    // read: Stripe sends the buyer back through\n    // /loot/return, which credits the pack before this page loads. It never\n    // gives up; it pauses while the sheet is closed (the purchase stays\n    // pending) and picks up again when it opens. The show's places follow\n    // from /ranks without holding the landing up (a cold leaderboard right\n    // after a deploy can be slow).\n    async awaitLoot() {\n      const show = this.cur\n      const tok = ++dom.landTok\n      const live = () => tok === dom.landTok && this.landing && this.fund && this.cur.id === show.id\n      const lp = this.landing.lp\n      const url = lp ? `/loot/balance?lp=${encodeURIComponent(lp)}` : '/loot/balance'\n      while (live()) {\n        const b = await fetch(url, { credentials: 'same-origin' })\n          .then((r) => (r.redirected ? { signedOut: true } : r.ok ? r.json() : null))\n          .catch(() => null)\n        if (!live()) return\n        // Signed out (sent to log in): nothing here can see it land.\n        if (b && b.signedOut) return (this.landing = null)\n        if (b && typeof b.total === 'number' && landed(b, this.landing, b.total)) {\n          headerLoot(b)\n          this.land({ ...(this.rank || {}), balance: b.total })\n          ranks.delete(show.slug)\n          this.loadRanks(show.slug).then((r) => {\n            if (!r || this.cur.id !== show.id) return\n            this.rank = r\n            this.places = placesFor(r, packs)\n          })\n          return\n        }\n        const waited = Date.now() - this.landing.t0\n        if (waited > LAND_SLOW_MS) this.landing.slow = true\n        await new Promise((done) => setTimeout(done, landPoll(waited)))\n      }\n    },\n    // It landed: the balance counts up to the new figure and the slider\n    // starts halfway through it (snapped to its step, within its range).\n    // It still reads as untouched: the handle nudges, the balance stays\n    // whole, and the line says to slide.\n    land(r) {\n      const from = this.balance\n      this.landed = this.landing.paid\n      this.landing = null\n      this.rank = r\n      this.places = placesFor(r, packs)\n      this.balance = r.balance\n      this.touched = false\n      const lo = this.minAmt()\n      this.amount = Math.max(lo, Math.min(this.maxAmt(), Math.round(r.balance / 2 / lo) * lo))\n      this.riseTo(from, r.balance)\n      this.$nextTick(() => this.focusControl())\n    },\n    // Back from a purchase, once it's in: what the line on the sheet says.\n    landedLine() {\n      return `${fmt(this.landed)} LOOT is in your wallet. Slide to choose how much to ${this.tipping ? 'tip' : 'put in'}.`\n    },\n    riseTo(from, to) {\n      if (calm() || to <= from) return\n      const t0 = performance.now()\n      const ms = 900\n      this.rise = from\n      const step = (t) => {\n        if (this.rise === null) return\n        const k = Math.min(1, (t - t0) / ms)\n        this.rise = from + (to - from) * (1 - Math.pow(1 - k, 3))\n        if (k < 1) requestAnimationFrame(step)\n        else this.rise = null\n      }\n      requestAnimationFrame(step)\n    },\n    // A purchase still landing stays pending: the sheet opens on it again.\n    closeFund() {\n      if (!this.fund) return\n      this.endTour()\n      this.fund = false\n      document.documentElement.classList.remove('sjf-lock')\n      const from = dom.fundFrom\n      dom.fundFrom = null\n      if (from && from.isConnected) from.focus({ preventScroll: true })\n    },\n    // \u2500\u2500 the \"?\" tour \u2500\u2500\n\n    // The steps whose parts show, read as the tour starts and kept for it:\n    // a part that comes and goes mid-tour (the place badge, while the\n    // slider step slides) mustn't shift the steps under the viewer.\n    tourSteps() {\n      if (this.tour >= 0 && this.tourList) return this.tourList\n      const panel = this.$refs.fundPanel\n      const plain = this.cur.crowdfunded === false\n      return ((this.tipping ? TIP_TOUR : TOUR)[this.mode] || [])\n        .filter((s) => {\n          const el = panel && panel.querySelector(s.sel)\n          return el && el.offsetParent !== null\n        })\n        .map((s) => (plain && s.plain ? Object.assign({}, s, { text: s.plain }) : s))\n    },\n    tourStep() {\n      return this.tourSteps()[this.tour] || { text: '' }\n    },\n    startTour() {\n      this.seenTour()\n      this.tourList = null\n      this.tourList = this.tourSteps()\n      this.tour = 0\n      this.$nextTick(() => this.showTourStep())\n    },\n    nextTour() {\n      if (this.tour < 0) return\n      if (this.tour >= this.tourSteps().length - 1) return this.endTour()\n      this.tour++\n      this.$nextTick(() => this.showTourStep())\n    },\n    endTour() {\n      this.stopDemo()\n      this.tour = -1\n    },\n    seenTour() {\n      if (!this.helpNew) return\n      this.helpNew = false\n      markTourSeen()\n    },\n    // Spotlight the step's part (a hole in a dim layer) and set the card\n    // below it, or above when it's near the foot of the sheet.\n    showTourStep() {\n      this.stopDemo()\n      const panel = this.$refs.fundPanel\n      const step = this.tourStep()\n      const el = step.sel && panel.querySelector(step.sel)\n      if (!el) return this.endTour()\n      el.scrollIntoView({ block: 'nearest' })\n      const p = panel.getBoundingClientRect()\n      const r = el.getBoundingClientRect()\n      const pad = 8\n      const top = r.top - p.top + panel.scrollTop - pad\n      const left = r.left - p.left - pad\n      const radius = Math.min(24, (r.height + pad * 2) / 2)\n      this.tourHole = `top:${top}px;left:${left}px;width:${r.width + pad * 2}px;height:${r.height + pad * 2}px;border-radius:${radius}px`\n      const below = r.bottom - p.top + 130 < p.height\n      this.tourCard = below ? `top:${top + r.height + pad * 2 + 10}px` : `top:${Math.max(8, top - 118)}px`\n      this.$nextTick(() => this.$refs.tourNext && this.$refs.tourNext.focus({ preventScroll: true }))\n      if (step.demo && !calm()) this.startDemo()\n    },\n    // The slider step shows what the slider does: the handle slides there\n    // and back on its own (without touching the balance), until the step ends.\n    startDemo() {\n      if (this.mode === 'spend') {\n        this.demoFrom = { amount: this.amount }\n        const lo = this.minAmt()\n        const hi = Math.max(lo, Math.round(this.maxAmt() * 0.45))\n        let up = true\n        const run = () => {\n          this.amount = up ? hi : lo\n          up = !up\n        }\n        run()\n        dom.demoT = setInterval(run, 1100)\n      } else {\n        this.demoFrom = { sel: this.fundSel }\n        let k = 0\n        const order = [this.fundSel, Math.max(0, this.fundSel - 1), Math.max(0, this.fundSel - 2), Math.max(0, this.fundSel - 1)]\n        dom.demoT = setInterval(() => {\n          k = (k + 1) % order.length\n          this.fundSel = order[k]\n        }, 750)\n      }\n    },\n    stopDemo() {\n      if (dom.demoT) clearInterval(dom.demoT)\n      dom.demoT = null\n      const from = this.demoFrom\n      this.demoFrom = null\n      if (!from) return\n      if ('amount' in from) this.amount = from.amount\n      if ('sel' in from) this.fundSel = from.sel\n    },\n\n    // Focus lands on the open mode's scrubber (or its button).\n    focusControl() {\n      const section = this.$refs.fundPanel.querySelector(this.mode === 'spend' ? '.sjf-spend' : '.sjf-buy')\n      const el = section && [...section.querySelectorAll('.sjf-range, .sjf-cta')].find((e) => e.offsetParent !== null)\n      if (el) el.focus({ preventScroll: true })\n    },\n    // Tab stays in the sheet while it is open.\n    fundKey(e) {\n      if (e.key === 'Tab') {\n        const stops = [...this.$refs.fundPanel.querySelectorAll('button, a[href], input')].filter(\n          (el) => el.tabIndex >= 0 && el.offsetParent !== null\n        )\n        const first = stops[0]\n        const last = stops[stops.length - 1]\n        if (e.shiftKey && document.activeElement === first) {\n          e.preventDefault()\n          last.focus()\n        } else if (!e.shiftKey && document.activeElement === last) {\n          e.preventDefault()\n          first.focus()\n        }\n      }\n    },\n    // Buying a pack (ShowsCheckoutController): paid or not, Stripe returns\n    // to this sheet.\n    checkoutPath() {\n      return `/shows/${encodeURIComponent(this.cur.slug)}/checkout`\n    },\n    // Signed out, the first Continue opens the account fields.\n    openSignup() {\n      this.signup = true\n      this.error = ''\n      this.$nextTick(() => {\n        const first = this.account === 'login' ? this.$refs.emailField : this.$refs.firstField\n        if (first) first.focus()\n      })\n    },\n    switchAccount() {\n      this.account = this.account === 'login' ? 'register' : 'login'\n      this.openSignup()\n    },\n\n    // \u2500\u2500 spending what you have (like the /x dock) \u2500\u2500\n\n    fmt,\n    // Up to the balance, and to what the show still needs once /ranks says\n    // (a tip can be the whole balance).\n    maxAmt() {\n      const room = !this.tipping && this.rank && this.rank.room >= 0 ? this.rank.room : Infinity\n      return Math.max(0, Math.min(this.balance, room))\n    },\n    // 100 a step, or less when that's all there is (the /x dock's floor).\n    minAmt() {\n      return Math.max(1, Math.min(100, this.maxAmt()))\n    },\n    // Where an amount sits along the slider, 0..100.\n    slid(amount) {\n      const lo = this.minAmt()\n      const hi = this.maxAmt()\n      if (hi <= lo) return 100\n      return Math.max(0, Math.min(100, ((amount - lo) / (hi - lo)) * 100))\n    },\n    // The range steps by the floor; the last step reaches the whole balance.\n    slide(raw) {\n      const v = parseInt(raw, 10) || 0\n      const hi = this.maxAmt()\n      this.amount = Math.max(this.minAmt(), v + this.minAmt() > hi ? hi : v)\n      this.touched = true\n      this.rise = null\n      this.error = ''\n    },\n    // The show's funded percent with this amount in (blitz-aware), drawn as\n    // /x draws it: any amount shows at least a sliver past the fill.\n    projected() {\n      const c = this.cur\n      if (!(c.goal > 0)) return 0\n      // Buying pledges the pack, up to what the show still needs.\n      const room = this.rank && this.rank.room >= 0 ? this.rank.room : Infinity\n      const n = this.mode === 'spend' ? this.amount : Math.min(this.pack().amount, room)\n      const raw = (((c.funded || 0) + n * (c.blitz || 1)) / c.goal) * 100\n      const floor = n > 0 ? Math.max(raw, ((c.funded || 0) / c.goal) * 100 + 0.8) : raw\n      return Math.min(100, floor)\n    },\n    placeNow() {\n      return placeAt(this.rank, this.amount)\n    },\n    // What stays in the balance: counting down while sliding, the real\n    // balance once the pledge has landed.\n    left() {\n      if (this.done || !this.touched) return this.balance\n      return Math.max(0, this.balance - this.amount)\n    },\n    // The next place up, if the slider can still reach it: the tick.\n    nextPlace() {\n      const r = this.rank\n      if (this.tipping || !r || !(r.room > 0)) return null\n      const place = (this.placeNow() || 5) - 1\n      const above = (r.top || [])[place - 1]\n      if (place < 1 || above == null) return null\n      const at = above + 1 - (r.mine || 0)\n      return at > this.amount && at <= this.maxAmt() ? { place, at } : null\n    },\n    // Produce it, or Tip it: the same POST, to /produce or /tip.\n    async produce() {\n      if (this.busy) return\n      const show = this.cur\n      const tipping = this.tipping\n      const body = new URLSearchParams({ amount: String(this.amount) })\n      if (!this.named && !tipping) body.set('credit_name', this.creditName.trim())\n      this.busy = true\n      this.error = ''\n      try {\n        const res = await fetch(`/shows/${encodeURIComponent(show.slug)}/${tipping ? 'tip' : 'produce'}`, {\n          method: 'POST',\n          credentials: 'same-origin',\n          headers: { 'x-csrf-token': csrf() },\n          body,\n        })\n        const r = await res.json().catch(() => ({}))\n        if (!res.ok) {\n          this.error = r.error || 'Something went wrong. Check your LOOT before trying again.'\n          return\n        }\n        this.balance = r.balance\n        headerLoot(r)\n        ranks.delete(show.slug)\n        this.seenTour()\n        if (tipping) {\n          this.done = { spent: r.spent, place: null }\n          clickyGoal('Tip')\n          return\n        }\n        // Place from the totals before this pledge (any place: Special\n        // Thanks too); then the show's numbers move here, and its /ranks is\n        // read fresh next time.\n        const place = creditAt(this.rank, r.spent)\n        show.funded = (show.funded || 0) + r.spent * (show.blitz || 1)\n        if (show.goal > 0) show.pct = show.funded >= show.goal ? 100 : Math.min(99, Math.floor((show.funded * 100) / show.goal))\n        this.rev++\n        this.named = true\n        this.done = { spent: r.spent, place }\n        clickyGoal('Produce')\n      } catch (_e) {\n        this.error = 'Something went wrong. Check your LOOT before trying again.'\n      } finally {\n        this.busy = false\n      }\n    },\n  }\n}\n", "// Conversions for the ad pixels (DoubloonWeb.AdEvents): Meta (Facebook +\n// Instagram ads), X and Google Ads (YouTube). window.loorAds names each LOOR\n// event per platform; a platform with no name for one never hears of it.\n// Sign-ups and purchases come with the page, on the Clicky goals; goals\n// reached inside a page arrive through clickyGoal (adGoal). The pixels load\n// only once analytics cookies are allowed, so each call waits for its\n// pixel's function (fbq, twq, gtag).\n\nconst POLL_MS = 500\nconst GIVE_UP_MS = 10 * 60 * 1000\n\nconst pending = []\nlet timer = null\nlet startedAt = 0\n\nfunction flush() {\n  for (const call of pending.splice(0)) {\n    const fn = window[call.fn]\n    if (typeof fn === 'function') fn(...call.args)\n    else pending.push(call)\n  }\n  return pending.length === 0\n}\n\nfunction send(fn, ...args) {\n  pending.push({ fn, args })\n  if (flush() || timer) return\n  startedAt = Date.now()\n  timer = setInterval(() => {\n    if (flush() || Date.now() - startedAt > GIVE_UP_MS) {\n      clearInterval(timer)\n      timer = null\n    }\n  }, POLL_MS)\n}\n\n// value is dollars; id is the one Meta's server copy carries too, so Meta\n// keeps one of the two.\nexport function adEvent(event, { value, id, content } = {}) {\n  const ads = window.loorAds\n  if (!ads || !event) return\n  const money = value ? { value: Number(value), currency: 'USD' } : {}\n\n  const meta = ads.meta.events[event] || ads.meta.custom[event]\n  if (meta) {\n    const how = ads.meta.events[event] ? 'track' : 'trackCustom'\n    const params = { ...money, ...content }\n    if (id) send('fbq', how, meta, params, { eventID: id })\n    else send('fbq', how, meta, params)\n  }\n\n  const x = ads.x.events[event]\n  if (x) send('twq', 'event', x, { ...money, ...(id && { conversion_id: id }) })\n\n  const google = ads.google && ads.google.events[event]\n  if (google)\n    send('gtag', 'event', 'conversion', {\n      send_to: google,\n      ...money,\n      ...(id && { transaction_id: id }),\n    })\n}\n\n// A Clicky goal reached inside a page (Produce, Tip, Pitch submitted).\nexport function adGoal(name) {\n  const event = window.loorAds && window.loorAds.goals[name]\n  if (event) adEvent(event)\n}\n\nexport function installAdEvents() {\n  if (!window.loorAds) return\n  for (const goal of window.loorClickyGoals || [])\n    for (const ad of goal.ads || []) adEvent(ad.event, ad)\n\n  // A show's own page, for Meta's audiences of people who looked at a show.\n  const show = window.location.pathname.match(/^\\/(?:show|x)\\/([^/]+)\\/?$/)\n  if (show)\n    adEvent('view_show', {\n      content: { content_ids: [show[1]], content_type: 'product' },\n    })\n}\n", "// Clicky goals (DoubloonWeb.ClickyGoals). Ones the server reached come with\n// the page (window.loorClickyGoals); a LiveView pushes \"clicky-goal\"; other\n// scripts call clickyGoal(). The tracker only loads once site-stats cookies\n// are allowed, so goals wait for it, and then a moment more so its own\n// pageview lands first and the goal joins that visit. Produce, Tip and\n// Pitch submitted go to the ad pixels too (ad_events.js).\n\nimport { adGoal } from './ad_events.js'\n\nconst POLL_MS = 500\nconst SETTLE_MS = 1000\nconst GIVE_UP_MS = 10 * 60 * 1000\n\nconst queue = []\nlet seenAt = 0\nlet timer = null\nlet startedAt = 0\n\nfunction flush() {\n  const clicky = window.clicky\n  if (!clicky || typeof clicky.goal !== 'function') return false\n  if (!seenAt) seenAt = Date.now()\n  if (Date.now() - seenAt < SETTLE_MS) return false\n  while (queue.length) {\n    const { name, revenue } = queue.shift()\n    clicky.goal(name, revenue || undefined)\n  }\n  return true\n}\n\nfunction wait() {\n  if (flush() || timer) return\n  startedAt = Date.now()\n  timer = setInterval(() => {\n    if (flush() || Date.now() - startedAt > GIVE_UP_MS) {\n      clearInterval(timer)\n      timer = null\n    }\n  }, POLL_MS)\n}\n\nexport function clickyGoal(name, revenue) {\n  if (!name) return\n  adGoal(name)\n  queue.push({ name, revenue })\n  wait()\n}\n\nexport function installClickyGoals() {\n  for (const goal of window.loorClickyGoals || [])\n    clickyGoal(goal.name, goal.revenue)\n  window.addEventListener('phx:clicky-goal', (e) =>\n    clickyGoal(e.detail.name, e.detail.revenue)\n  )\n}\n", "// lootSheet \u2014 the LOOT picker on every page (DoubloonWeb.LootSheet,\n// loot_sheet.css): the /shows fund sheet's packs on their own, the one way\n// to buy LOOT. Anything opens it with a `loot:buy` window event (the\n// header's +, Buy LOOT in the menu, /profile, the show pages, /x), or with\n// ?buy=1 on the page's address. The packs snap along one scrubber, smallest\n// left; the pill counts the pack's LOOT and bonus up as it climbs. Continue\n// is a real form POST to Stripe Checkout (LootCheckoutController, or /x's\n// own endpoints there), which comes back to this same page:\n//   * paid (?loot_paid=<LOOT>&loot_pre=<balance before>&lp=<Checkout\n//     Session>, lp= added by /loot/return): the sheet opens on the LOOT\n//     landing and asks /loot/balance?lp= until that purchase is credited\n//     (usually the first read: the return credits it before the page\n//     loads), then ticks and shows it in the header. Without lp= (a\n//     checkout opened before the return hop) it waits for the balance to\n//     reach loot_pre + loot_paid;\n//   * left unpaid, or it didn't open (?buy=1, maybe &loot_err=, and\n//     &loot_msg= for a validation message): on the packs, as they were left.\n// The keys are the sheet's own (/x passes express_error/message), so they\n// never collide with /shows's fund sheet, which reads err=.\n\nconst calm = () => window.matchMedia('(prefers-reduced-motion: reduce)').matches\n\n// Back from a purchase: read the balance this often until it lands; slower\n// once it's taking a while (the \"Taking longer\" note shows), and slower\n// again after a minute. It never gives up, and keeps going with the sheet\n// closed (it opens on the pending purchase again, never on the packs).\nconst LAND_POLL_MS = 2000\nconst LAND_SLOW_MS = 20000\nconst LAND_SLOW_POLL_MS = 6000\nconst LAND_LATE_MS = 60000\nconst LAND_LATE_POLL_MS = 10000\nconst landPoll = (waited) => (waited > LAND_LATE_MS ? LAND_LATE_POLL_MS : waited > LAND_SLOW_MS ? LAND_SLOW_POLL_MS : LAND_POLL_MS)\n\nconst CHECKOUT_ERRORS = {\n  stripe: \"Payment didn't open. Try again.\",\n  amount: 'Pick a pack and try again.',\n  email_taken: 'That email has an account. Log in.',\n  bad_login: \"That email and password don't match.\",\n  rate_limited: 'Too many tries. Wait a few minutes.',\n  expired: 'Page expired. Try again.',\n  invite_only: 'This page is invite only for now.',\n}\n\n// The address keys the sheet reads on the way back, cleared once read.\nconst KEYS = ['buy', 'loot_paid', 'loot_pre', 'lp', 'amount', 'member', 'mode', 'credit_name', 'email']\n\nconst fmt = (n) => Math.round(n || 0).toLocaleString('en-US')\n\n// A purchase has landed when /loot/balance says its Checkout Session (lp)\n// is credited; a page without lp falls back to the balance reaching\n// pre + paid.\nexport const landed = (r, landing, balance) =>\n  landing.lp ? !!(r.purchase && r.purchase.credited) : typeof balance === 'number' && balance >= landing.want\n\nexport default ({ packs = [], signedIn = false, member = false, errParam = 'loot_err', msgParam = 'loot_msg', messages = {}, startOpen = false } = {}) => {\n  const recIdx = Math.max(0, packs.findIndex((p) => p.rec))\n  const errors = Object.assign({}, CHECKOUT_ERRORS, messages)\n  // A pack asked for by amount (the /x dock's pick): that one, else the\n  // smallest that holds it, else the recommended one.\n  const packFor = (amount) => {\n    if (!(amount > 0)) return recIdx\n    const exact = packs.findIndex((p) => p.amount === amount)\n    if (exact >= 0) return exact\n    let k = -1\n    packs.forEach((p, i) => {\n      if (p.amount >= amount && (k < 0 || p.amount < packs[k].amount)) k = i\n    })\n    return k >= 0 ? k : recIdx\n  }\n  const dom = { from: null, countTok: 0 }\n\n  return {\n    open: false,\n    fundSel: recIdx,\n    // the pill's numbers as they count: the pack's LOOT, and how much more\n    // LOOT its bonus gives (percent)\n    tick: { loot: 0, more: 0, pop: false },\n    signedIn,\n    member,\n    join: false,\n    signup: false,\n    account: 'register',\n    typed: { credit_name: '', email: '' },\n    sending: false,\n    error: '',\n    // back from a purchase: waiting for it to land ({ paid, want, slow }),\n    // then what landed\n    landing: null,\n    landed: 0,\n\n    fmt,\n    pack() {\n      return packs[this.fundSel] || { amount: 0, price: '', label: '', g: 0, more: 0, bonus: 0 }\n    },\n    get packCount() {\n      return packs.length\n    },\n    // Where the picked pack sits on the scrubber (smallest left), 0..100.\n    packAt() {\n      return packs.length > 1 ? ((packs.length - 1 - this.fundSel) / (packs.length - 1)) * 100 : 100\n    },\n    shown() {\n      if (this.landed) return this.landed\n      if (this.landing) return this.landing.paid\n      return this.tick.loot\n    },\n    // The pill counts up (or down) to the picked pack's LOOT and bonus.\n    countTo(now = false) {\n      const p = this.pack()\n      const from = { loot: this.tick.loot, more: this.tick.more }\n      const tok = ++dom.countTok\n      if ((p.more || 0) > from.more && !now) {\n        this.tick.pop = true\n        setTimeout(() => tok === dom.countTok && (this.tick.pop = false), 180)\n      }\n      const ms = now || calm() ? 0 : 450\n      const t0 = performance.now()\n      const step = (t) => {\n        if (tok !== dom.countTok) return\n        const k = ms ? Math.min(1, (t - t0) / ms) : 1\n        const e = 1 - Math.pow(1 - k, 3)\n        this.tick.loot = from.loot + (p.amount - from.loot) * e\n        this.tick.more = from.more + ((p.more || 0) - from.more) * e\n        if (k < 1) requestAnimationFrame(step)\n      }\n      ms ? requestAnimationFrame(step) : step(t0)\n    },\n\n    init() {\n      this.$watch('fundSel', () => this.countTo())\n      // Back from Stripe to a page kept whole: the form can go again.\n      window.addEventListener('pageshow', (e) => e.persisted && (this.sending = false))\n\n      const qs = new URLSearchParams(location.search)\n      const paid = parseInt(qs.get('loot_paid'), 10)\n      const pre = parseInt(qs.get('loot_pre'), 10)\n      const lp = qs.get('lp')\n      const errKey = qs.get(errParam)\n      // Read before the keys come off the address below.\n      const msg = qs.get(msgParam) || ''\n      const buy = qs.get('buy') === '1' || !!errKey\n      if (!(paid > 0) && !buy) return startOpen && this.openSheet()\n\n      const back = {\n        amount: parseInt(qs.get('amount'), 10),\n        join: qs.get('member') === '1',\n        account: qs.get('mode') === 'login' ? 'login' : 'register',\n        typed: { credit_name: qs.get('credit_name') || '', email: qs.get('email') || '' },\n      }\n      for (const k of KEYS.concat(errParam, msgParam)) qs.delete(k)\n      const rest = qs.toString()\n      try {\n        history.replaceState(history.state, '', location.pathname + (rest ? '?' + rest : '') + location.hash)\n      } catch (_e) {}\n\n      if (paid > 0) {\n        this.landing = { paid, lp, want: (pre >= 0 ? pre : 0) + paid, slow: false }\n        this.openSheet()\n        return this.awaitLoot()\n      }\n      this.openSheet({ amount: back.amount })\n      this.join = back.join\n      this.account = back.account\n      this.typed = back.typed\n      if (back.typed.email || (errKey && errKey !== 'stripe' && errKey !== 'amount')) this.signup = !signedIn\n      this.error = errKey === 'validation' ? msg : errors[errKey] || msg\n    },\n\n    openSheet(detail) {\n      if (this.open) return\n      dom.from = document.activeElement\n      if (!this.landing) {\n        this.fundSel = packFor(detail && parseInt(detail.amount, 10))\n        this.landed = 0\n        this.error = ''\n        this.signup = false\n      }\n      this.countTo(true)\n      this.open = true\n      document.documentElement.classList.add('sjf-lock')\n      this.$nextTick(() => this.focusControl())\n    },\n    // A purchase still landing stays pending (awaitLoot keeps reading).\n    closeSheet() {\n      if (!this.open) return\n      this.open = false\n      document.documentElement.classList.remove('sjf-lock')\n      const from = dom.from\n      dom.from = null\n      if (from && from.isConnected) from.focus({ preventScroll: true })\n    },\n\n    // Waiting for a purchase to land: until /loot/balance says this\n    // purchase (lp) is credited, whatever else the balance did meanwhile;\n    // without lp, until the balance holds what was bought. Then show it\n    // wherever the page shows the balance.\n    async awaitLoot() {\n      const t0 = Date.now()\n      const lp = this.landing.lp\n      const url = lp ? `/loot/balance?lp=${encodeURIComponent(lp)}` : '/loot/balance'\n      while (this.landing) {\n        const r = await fetch(url, { credentials: 'same-origin' })\n          .then((res) => (res.redirected ? { signedOut: true } : res.ok ? res.json() : null))\n          .catch(() => null)\n        if (!this.landing) return\n        // Signed out (sent to log in): nothing here can see it land.\n        if (r && r.signedOut) return (this.landing = null)\n        if (r && landed(r, this.landing, r.balance)) return this.land(r)\n        const waited = Date.now() - t0\n        if (waited > LAND_SLOW_MS) this.landing.slow = true\n        await new Promise((done) => setTimeout(done, landPoll(waited)))\n      }\n    },\n    land(r) {\n      this.landed = this.landing.paid\n      this.landing = null\n      for (const el of document.querySelectorAll('[data-loot-gold]')) el.textContent = String(r.gold)\n      this.$nextTick(() => this.focusControl())\n    },\n\n    focusControl() {\n      const panel = this.$refs.panel\n      const el = panel && [...panel.querySelectorAll('.sjf-range, .sjf-cta')].find((e) => e.offsetParent !== null)\n      if (el) el.focus({ preventScroll: true })\n    },\n    // Tab stays in the sheet while it is open; Escape closes it.\n    key(e) {\n      if (e.key === 'Escape') return this.closeSheet()\n      if (e.key !== 'Tab') return\n      const stops = [...this.$refs.panel.querySelectorAll('button, a[href], input')].filter(\n        (el) => el.tabIndex >= 0 && el.offsetParent !== null\n      )\n      const first = stops[0]\n      const last = stops[stops.length - 1]\n      if (e.shiftKey && document.activeElement === first) {\n        e.preventDefault()\n        last.focus()\n      } else if (!e.shiftKey && document.activeElement === last) {\n        e.preventDefault()\n        first.focus()\n      }\n    },\n    // Signed out, the first Continue opens the account fields.\n    openSignup() {\n      this.signup = true\n      this.error = ''\n      this.$nextTick(() => {\n        const first = this.account === 'login' ? this.$refs.emailField : this.$refs.firstField\n        if (first) first.focus()\n      })\n    },\n    switchAccount() {\n      this.account = this.account === 'login' ? 'register' : 'login'\n      this.openSignup()\n    },\n  }\n}\n", "// joinSheet \u2014 Join Now on every page (DoubloonWeb.JoinSheet, loot_sheet.css):\n// the LOOT picker's sheet with only its account fields. Anything opens it\n// with a `loot:join` window event (the header's Sign up and Log in, the\n// landing's Sign up), or with ?join=1 (&mode=login) on the page's address. Join is a real form\n// POST (JoinController), which signs the browser in and comes back to this\n// same page; a sign-up that didn't go through comes back with ?join=1, the\n// join_err= key (and join_msg= for a validation message) and what was typed.\n\nconst ERRORS = {\n  email_taken: 'That email has an account. Log in.',\n  bad_login: \"That email and password don't match.\",\n  rate_limited: 'Too many tries. Wait a few minutes.',\n  expired: 'That page expired. Try again.',\n}\n\n// The address keys the sheet reads on the way back, cleared once read.\nconst KEYS = ['join', 'join_err', 'join_msg', 'mode', 'first_name', 'last_name', 'email']\n\nexport default () => {\n  const dom = { from: null }\n\n  return {\n    open: false,\n    account: 'register',\n    typed: { first_name: '', last_name: '', email: '' },\n    sending: false,\n    error: '',\n\n    init() {\n      // Back to a page kept whole: the form can go again.\n      window.addEventListener('pageshow', (e) => e.persisted && (this.sending = false))\n\n      const qs = new URLSearchParams(location.search)\n      const errKey = qs.get('join_err')\n      if (qs.get('join') !== '1' && !errKey) return\n\n      const msg = qs.get('join_msg') || ''\n      this.account = qs.get('mode') === 'login' ? 'login' : 'register'\n      this.typed = {\n        first_name: qs.get('first_name') || '',\n        last_name: qs.get('last_name') || '',\n        email: qs.get('email') || '',\n      }\n      for (const k of KEYS) qs.delete(k)\n      const rest = qs.toString()\n      try {\n        history.replaceState(history.state, '', location.pathname + (rest ? '?' + rest : '') + location.hash)\n      } catch (_e) {}\n\n      this.openSheet()\n      this.error = errKey === 'validation' ? msg : ERRORS[errKey] || msg\n    },\n\n    // From a button, `opts.mode` picks Sign up or Log in; from the address,\n    // init() has already set it.\n    openSheet(opts) {\n      if (this.open) return\n      if (opts) this.account = opts.mode === 'login' ? 'login' : 'register'\n      dom.from = document.activeElement\n      this.error = ''\n      this.open = true\n      document.documentElement.classList.add('sjf-lock')\n      this.$nextTick(() => this.focusFirst())\n    },\n    closeSheet() {\n      if (!this.open) return\n      this.open = false\n      document.documentElement.classList.remove('sjf-lock')\n      const from = dom.from\n      dom.from = null\n      if (from && from.isConnected) from.focus({ preventScroll: true })\n    },\n\n    focusFirst() {\n      const first = this.account === 'login' ? this.$refs.emailField : this.$refs.firstField\n      if (first) first.focus({ preventScroll: true })\n    },\n    // Tab stays in the sheet while it is open; Escape closes it.\n    key(e) {\n      if (e.key === 'Escape') return this.closeSheet()\n      if (e.key !== 'Tab') return\n      const stops = [...this.$refs.panel.querySelectorAll('button, a[href], input')].filter(\n        (el) => el.tabIndex >= 0 && el.offsetParent !== null && !el.disabled\n      )\n      const first = stops[0]\n      const last = stops[stops.length - 1]\n      if (e.shiftKey && document.activeElement === first) {\n        e.preventDefault()\n        last.focus()\n      } else if (!e.shiftKey && document.activeElement === last) {\n        e.preventDefault()\n        first.focus()\n      }\n    },\n    switchAccount() {\n      this.account = this.account === 'login' ? 'register' : 'login'\n      this.error = ''\n      this.$nextTick(() => this.focusFirst())\n    },\n  }\n}\n", "// PROJECT X \u2014 Alpine data for the /x/:slug funding page.\n//\n// Two sliders share the same anatomy (gold fill + custom thumb over a hidden\n// native range) and the same preview wiring: moving one dispatches\n// px:preview {amount} (the RankPreview hook paints the projected credits\n// panel) and px:fund-preview {pct} (the vertical funding bar stretches its\n// striped preview segment to the projected total).\n//\n// Fill and thumb geometry is declarative (x-bind:style in the markup) so the\n// Alpine-LiveView clone bridge re-applies it after every LV patch; imperative\n// style writes would be wiped by the first patch after connect.\n\n// Dock allocation slider: continuous LOOT amounts from the balance.\n// The ceiling is read from the range input's max attribute at USE time,\n// not from cloned Alpine state: after a pledge, LiveView re-renders the\n// input with the shrunken max, and stale state would let the thumb sail\n// past the real remaining balance.\n//\n// Keeping the native range and the Alpine state in step across LV patches:\n//  - keepRangeValue (below, wired into LiveView's onBeforeElUpdated) stops the\n//    patch from resetting the range's value PROPERTY to its server-rendered\n//    value attribute (morphdom syncs unfocused inputs that way, and that is\n//    a property write, so no attribute mutation shows it);\n//  - a MutationObserver on the range's value/min/max attributes re-clamps the\n//    Alpine value when the server moves the ceiling (a new balance, a pledge\n//    that shrinks what the project still needs) and rewrites range.value, so\n//    the thumb, the native control and the Fund amount agree. Setting the\n//    .value property never changes the attribute, so it can't re-trigger it.\n//    The range snaps to its step (min), so a ceiling like 3050 is reachable\n//    only as 3000: every write goes through setValue(), which reads the\n//    browser's snapped value back into state so the Fund amount is never an\n//    amount the native control can't hold.\n//\n// The x-data attribute is a constant (\"pxSlider\", no arguments): Alpine\n// 3.9.5 treats a changed x-data attribute as a new component \u2014 it destroys\n// this instance and starts another, while the thumb, the Fund label and\n// phx-value-amount stay bound to the dead one. So nothing that changes\n// during a visit is passed in: the floor and ceiling come from the range\n// input, the project's funded/goal from data-funded/data-goal on the root,\n// all read when used. min/max below are state copies kept only so Alpine\n// re-renders the bindings that read them (resync() refreshes them).\nexport function pxSlider() {\n  return {\n    value: 0,\n    min: 0,\n    max: 0,\n    obs: null,\n    dockObs: null,\n    lastBalance: null,\n\n    init() {\n      const range = this.$refs.range\n      if (!range) return\n      this.min = this.minNow()\n      this.max = this.maxNow()\n      this.value = Math.min(parseInt(range.value, 10) || 0, this.maxNow())\n      this.$dispatch('px:alloc-preview', { amount: this.value })\n\n      this.obs = new MutationObserver(() => this.resync())\n      this.obs.observe(range, { attributes: true, attributeFilter: ['value', 'min', 'max'] })\n\n      // A pledge landing is the server spending balance: #px-dock's\n      // data-balance drops (the same signal the header balance follows). The\n      // projected seat then gives way to the real credits panel.\n      const dock = this.$el.closest('#px-dock')\n      if (dock) {\n        this.lastBalance = parseInt(dock.dataset.balance, 10)\n        this.dockObs = new MutationObserver(() => this.balanceChanged(dock))\n        this.dockObs.observe(dock, { attributes: true, attributeFilter: ['data-balance'] })\n      }\n    },\n\n    destroy() {\n      if (this.obs) this.obs.disconnect()\n      if (this.dockObs) this.dockObs.disconnect()\n      // The dock is leaving the page (fully funded, navigated away): don't\n      // leave a projection painted over the real panel, or the header stuck\n      // on the pledge countdown. Dispatched on window directly \u2014 this\n      // element may already be detached.\n      window.dispatchEvent(new CustomEvent('px:preview-end'))\n      window.dispatchEvent(new CustomEvent('px:alloc-end'))\n    },\n\n    balanceChanged(dock) {\n      const bal = parseInt(dock.dataset.balance, 10)\n      const prev = this.lastBalance\n      this.lastBalance = bal\n      // Only a drop is a pledge; a top-up raises the balance and the held\n      // projection stays valid.\n      if (!Number.isNaN(bal) && prev !== null && !Number.isNaN(prev) && bal < prev) this.endPreview()\n    },\n\n    // The range's attributes changed under us: pull the ceiling/floor into\n    // state (trackPct depends on them, so the thumb re-renders), clamp the\n    // held value, and make the native control show it.\n    resync() {\n      const range = this.$refs.range\n      if (!range) return\n      const max = this.maxNow()\n      const floor = this.minNow()\n      this.max = max\n      this.min = floor\n      const prev = this.value\n      this.setValue(Math.min(Math.max(prev, floor), max))\n      if (this.value !== prev) this.$dispatch('px:alloc-preview', { amount: this.value, user: false })\n    },\n\n    // Write an amount to the native range and take back what it actually\n    // holds (step-snapped, clamped to its min/max).\n    setValue(amount) {\n      const range = this.$refs.range\n      if (!range) {\n        this.value = amount\n        return\n      }\n      range.value = amount\n      const held = parseInt(range.value, 10)\n      this.value = Number.isNaN(held) ? amount : held\n    },\n\n    // Server push (LiveView push_event \"px:spotlight\"): a purchase just\n    // landed while the slider was already on the page, so jump it to the\n    // most the person can now put in.\n    spotlight() {\n      this.setValue(this.maxNow())\n      this.$dispatch('px:alloc-preview', { amount: this.value, user: false })\n    },\n\n    maxNow() {\n      const m = parseInt(this.$refs.range && this.$refs.range.max, 10)\n      return Number.isNaN(m) ? this.max : m\n    },\n\n    minNow() {\n      const m = parseInt(this.$refs.range && this.$refs.range.min, 10)\n      return Number.isNaN(m) ? this.min : m\n    },\n\n    trackPct() {\n      // Read the state copy purely as a reactive dependency: resync() assigns\n      // it when the range's max attribute changes, which re-runs the bindings\n      // that call this (maxNow() itself reads the DOM, which Alpine can't see).\n      void this.max\n      const max = this.maxNow()\n      // Self-heal after a patch shrinks the ceiling below the held value.\n      if (this.value > max) {\n        this.setValue(max)\n        this.$dispatch('px:alloc-preview', { amount: this.value })\n      }\n      return max > 0 ? (this.value / max) * 100 : 0\n    },\n\n    update(raw) {\n      const max = this.maxNow()\n      const val = Math.min(parseInt(raw, 10) || 0, max)\n\n      // At-max bump: once on ARRIVING at the ceiling \u2014 re-firing on every\n      // input event while pinned forces a reflow per tick (flicker).\n      const atMax = parseInt(raw, 10) >= max\n      if (this.$refs.thumb && atMax && !this._wasAtMax) {\n        this.$refs.thumb.classList.remove('at-max')\n        void this.$refs.thumb.offsetWidth\n        this.$refs.thumb.classList.add('at-max')\n      }\n      this._wasAtMax = atMax\n\n      this.value = val\n      if (this.$refs.range) this.$refs.range.value = val\n      // update() only ever runs from the range's own input event, so this is\n      // the one dispatch that means \"the person moved the slider\".\n      this.preview(true)\n    },\n\n    startPreview() {\n      this.preview()\n    },\n\n    // The projection holds for as long as the slider holds an amount above\n    // its starting minimum \u2014 releasing the thumb does not clear it. Back at\n    // the minimum there is nothing to project, so it clears. (A pledge\n    // landing clears it too: balanceChanged.)\n    preview(user = false) {\n      this.$dispatch('px:alloc-preview', { amount: this.value, user })\n      if (this.value <= this.minNow()) {\n        this.endPreview()\n        return\n      }\n      this.$dispatch('px:preview', { amount: this.value })\n      this.previewBar(this.value)\n    },\n\n    previewBar(amount) {\n      const { funded, goal } = fundingFrom(this.$root)\n      this.$dispatch('px:fund-preview', { pct: projectedPct(funded, goal, amount) })\n    },\n\n    endPreview() {\n      this.$dispatch('px:preview-end')\n    },\n  }\n}\n\n// LiveView's onBeforeElUpdated: when the dock's range is about to be patched,\n// carry its current value onto the incoming element so morphdom doesn't reset\n// the native control to the server-rendered default (a pledge attempt, a\n// balance broadcast and any other dock re-render would otherwise leave the\n// thumb and Fund label at the held amount while the range snapped back).\n// The browser clamps the value to the new element's min/max/step, and the\n// slider's own MutationObserver reconciles the Alpine state to that.\nexport function keepRangeValue(from, to) {\n  if (\n    from.tagName === 'INPUT' &&\n    from.type === 'range' &&\n    to.tagName === 'INPUT' &&\n    (from.closest('#px-funding-controls') || from.closest('#px-tip-controls'))\n  ) {\n    to.value = from.value\n  }\n}\n\n// The tip slider on a fully funded page (0 \u2192 the funder's balance). Unlike\n// pxSlider it projects nothing: a tip moves no seat and no funding bar. The\n// same constant-x-data rule applies, so the ceiling is read from the range\n// input, and a MutationObserver re-reads the (browser-clamped) value when a\n// tip lands and the server lowers the max.\nexport function pxTip() {\n  return {\n    value: 0,\n    max: 0,\n    obs: null,\n\n    init() {\n      const range = this.$refs.range\n      if (!range) return\n      this.sync()\n      this.obs = new MutationObserver(() => this.sync())\n      this.obs.observe(range, { attributes: true, attributeFilter: ['value', 'min', 'max'] })\n    },\n\n    destroy() {\n      if (this.obs) this.obs.disconnect()\n    },\n\n    sync() {\n      const range = this.$refs.range\n      this.max = parseInt(range.max, 10) || 0\n      this.value = Math.min(parseInt(range.value, 10) || 0, this.max)\n    },\n\n    update(raw) {\n      this.value = Math.min(parseInt(raw, 10) || 0, this.max)\n    },\n\n    trackPct() {\n      return this.max > 0 ? (this.value / this.max) * 100 : 0\n    },\n  }\n}\n\n// Header balance: the header lives in the ROOT layout, outside LiveView's\n// patch area, so it can never update itself. The dock carries the server's\n// truth in #px-dock's data-balance attribute (refreshed on every LV patch); a\n// MutationObserver mirrors it here so the two can never disagree.\n//\n// It always shows the full balance \u2014 the same silver + gold the rest of LOOR\n// shows in its header (decided 2026-10-21). It used to count down to \"LOOT\n// left after this pledge\" while the slider moved, which made /x read 100\n// lower than the main site with the slider resting at its 100 minimum. The\n// amount being pledged is on the Fund button.\nexport function pxHeaderBalance() {\n  return {\n    obs: null,\n\n    render() {\n      const out = this.$el.querySelector('[data-balance-text]')\n      const dock = document.querySelector('#px-dock[data-balance]')\n      if (!out || !dock) return\n      const bal = parseInt(dock.dataset.balance, 10)\n      if (!Number.isNaN(bal)) out.textContent = bal.toLocaleString()\n    },\n\n    init() {\n      this.obs = new MutationObserver(() => this.render())\n      this.obs.observe(document.body, {\n        subtree: true,\n        attributes: true,\n        attributeFilter: ['data-balance'],\n      })\n      this.render()\n    },\n\n    destroy() {\n      if (this.obs) this.obs.disconnect()\n    },\n  }\n}\n\n// Share: copies the page's canonical URL (params stripped) for pasting\n// anywhere. `copied` drives the button's feedback for a couple seconds.\nexport function pxShare() {\n  return {\n    copied: false,\n    _t: null,\n\n    share() {\n      const url = window.location.origin + window.location.pathname\n      const done = () => {\n        this.copied = true\n        clearTimeout(this._t)\n        this._t = setTimeout(() => (this.copied = false), 2000)\n      }\n\n      if (navigator.clipboard && navigator.clipboard.writeText) {\n        navigator.clipboard\n          .writeText(url)\n          .then(done)\n          .catch(() => pxCopyFallback(url) && done())\n      } else if (pxCopyFallback(url)) {\n        done()\n      }\n    },\n  }\n}\n\nfunction pxCopyFallback(text) {\n  const ta = document.createElement('textarea')\n  ta.value = text\n  ta.style.position = 'fixed'\n  ta.style.opacity = '0'\n  document.body.appendChild(ta)\n  ta.select()\n  let ok = false\n  try {\n    ok = document.execCommand('copy')\n  } catch (_e) {\n    ok = false\n  }\n  ta.remove()\n  return ok\n}\n\n// The Producers tab's film crawl. Scroll-driven (not a CSS animation) so the\n// viewer can take over with the wheel or a finger. Two stacked copies of the\n// roll make the auto-crawl loop seamless \u2014 passing the first copy's height\n// wraps silently back by one copy. Hovering pauses the crawl.\n//\n// The first time the viewer scrolls it themselves (wheel, touch, pointer,\n// keys, or any scroll we didn't cause), the roll goes manual for the rest of\n// the visit: the crawl stops, the position folds into the first copy, and the\n// second copy is hidden so the credits scroll through once and end instead of\n// repeating. Visitors who prefer reduced motion start in manual mode.\nexport function pxRoll() {\n  return {\n    hovering: false,\n    isManual: false,\n    raf: null,\n    last: null,\n    expected: 0, // the scrollTop our last auto write produced\n    lastHeight: 0, // scrollHeight when expected was last taken\n    speed: 36, // px/second\n\n    init() {\n      const el = this.$el\n      this.expected = el.scrollTop\n      this.lastHeight = el.scrollHeight\n\n      if (window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) {\n        this.manual()\n        return\n      }\n\n      const tick = (ts) => {\n        if (this.last === null) this.last = ts\n        const dt = Math.min((ts - this.last) / 1000, 0.1)\n        this.last = ts\n        this.rebaseIfResized()\n        const copy = el.scrollHeight / 2\n        if (copy <= 0) {\n          // Pane hidden (display: none resets scrollTop): re-baseline.\n          this.expected = el.scrollTop\n        } else if (!this.hovering) {\n          el.scrollTop += this.speed * dt\n          if (el.scrollTop >= copy) el.scrollTop -= copy\n          this.expected = el.scrollTop\n        }\n        this.raf = requestAnimationFrame(tick)\n      }\n      this.raf = requestAnimationFrame(tick)\n    },\n\n    destroy() {\n      cancelAnimationFrame(this.raf)\n    },\n\n    // Scroll events arrive a frame after the write that caused them, so a\n    // flag around the write can't tell them apart. Compare the position to\n    // what the auto-scroll last left instead: anything else was the viewer\n    // (or the browser acting for them, e.g. find-in-page).\n    scrolled() {\n      if (this.isManual) return\n      const el = this.$el\n      if (el.scrollHeight <= 0 || el.clientHeight === 0) return\n      if (this.rebaseIfResized()) return\n      if (Math.abs(el.scrollTop - this.expected) > 1.5) this.manual()\n    },\n\n    // The roll's content changed size (a backer added or reordered by a\n    // LiveView patch): any scrollTop shift that came with it \u2014 the browser\n    // clamping, or anchoring if .px-roll's overflow-anchor: none were lost \u2014\n    // is not the viewer scrolling. Take the current position as the new\n    // baseline. Returns true when it re-baselined.\n    rebaseIfResized() {\n      const el = this.$el\n      if (el.scrollHeight === this.lastHeight) return false\n      this.lastHeight = el.scrollHeight\n      this.expected = el.scrollTop\n      return true\n    },\n\n    key(e) {\n      if (e.target !== this.$el) return\n      if (['ArrowUp', 'ArrowDown', 'PageUp', 'PageDown', 'Home', 'End', ' '].includes(e.key)) {\n        this.manual()\n      }\n    },\n\n    manual() {\n      if (this.isManual) return\n      this.isManual = true\n      const el = this.$el\n      cancelAnimationFrame(this.raf)\n      this.raf = null\n\n      // Fold the position into the first copy (the copies are identical, so\n      // the fold is invisible). The second copy hides through its\n      // x-bind:hidden=\"isManual\" binding \u2014 a reactive binding, so LiveView\n      // patches can't undo it \u2014 which Alpine applies after this returns, so\n      // the measurement here still sees both copies.\n      const copy = el.scrollHeight / 2\n      const pos = copy > 0 ? el.scrollTop % copy : 0\n      el.scrollTop = pos\n    },\n  }\n}\n\n// Buy-modal ladder: a slider whose notches are the real Stripe LOOT packages\n// (amounts + the credit seat they'd reach \u2014 never a currency). The CTA reads\n// current().amount via x-bind.\n//\n// Constant x-data like pxSlider: the rows (data-ladder, JSON) and the\n// project's funded/goal (data-funded/data-goal) change as people pledge, so\n// they ride on data attributes \u2014 the rows mirrored into state by watchData()\n// (the seat labels are rendered reactively), funded/goal read when used.\nexport function pxLadder() {\n  return {\n    ladder: [],\n    idx: 0,\n    obs: null,\n\n    init() {\n      this.ladder = jsonData(this.$root, 'ladder', [])\n      const range = this.$refs.range\n      this.idx = Math.max(Math.min(parseInt(range?.value, 10) || 0, this.ladder.length - 1), 0)\n      this.obs = watchData(this.$root, ['data-ladder'], () => {\n        this.ladder = jsonData(this.$root, 'ladder', [])\n        this.idx = Math.max(Math.min(this.idx, this.ladder.length - 1), 0)\n      })\n    },\n\n    destroy() {\n      if (this.obs) this.obs.disconnect()\n    },\n\n    current() {\n      return this.ladder[this.idx] || { amount: 0, label: null, price: null }\n    },\n\n    // px:open-buy can carry the amount picked elsewhere (the dock's starter\n    // ladder) so the buy screen opens with that package highlighted.\n    preset(detail) {\n      const amount = detail && detail.amount\n      if (!amount) return\n      const i = this.ladder.findIndex((p) => p.amount === amount)\n      if (i >= 0) this.update(i)\n    },\n\n    fmt(n) {\n      return (n || 0).toLocaleString()\n    },\n\n    trackPct() {\n      return this.ladder.length > 1 ? (this.idx / (this.ladder.length - 1)) * 100 : 0\n    },\n\n    update(raw) {\n      const val = Math.min(Math.max(parseInt(raw, 10) || 0, 0), this.ladder.length - 1)\n\n      if (this.$refs.thumb && val === this.ladder.length - 1) {\n        this.$refs.thumb.classList.remove('at-max')\n        void this.$refs.thumb.offsetWidth\n        this.$refs.thumb.classList.add('at-max')\n      }\n\n      this.idx = val\n      if (this.$refs.range) this.$refs.range.value = val\n      this.preview()\n    },\n\n    preview() {\n      const { funded, goal } = fundingFrom(this.$root)\n      this.$dispatch('px:preview', { amount: this.current().amount })\n      this.$dispatch('px:fund-preview', {\n        pct: projectedPct(funded, goal, this.current().amount),\n      })\n    },\n\n    endPreview() {\n      this.$dispatch('px:preview-end')\n    },\n  }\n}\n\n// The project's live funded/goal totals, server-rendered as data-funded /\n// data-goal on a component's root and read at use time (never baked into\n// x-data \u2014 see pxSlider). Callers pass this.$root: inside a method run from\n// a child's handler (the range's x-on:input) Alpine's this.$el is that child.\nfunction fundingFrom(el) {\n  const num = (v) => {\n    const n = parseInt(v, 10)\n    return Number.isNaN(n) ? 0 : n\n  }\n  return { funded: num(el.dataset.funded), goal: num(el.dataset.goal) }\n}\n\n// JSON from a data-* attribute (camelCase dataset key), or the fallback.\nfunction jsonData(el, key, fallback) {\n  try {\n    const raw = el.dataset[key]\n    return raw ? JSON.parse(raw) : fallback\n  } catch (_e) {\n    return fallback\n  }\n}\n\n// Calls onChange whenever one of these attributes on el changes (a LiveView\n// patch rewriting server data). Returns the observer for destroy().\nfunction watchData(el, attrs, onChange) {\n  const obs = new MutationObserver(onChange)\n  obs.observe(el, { attributes: true, attributeFilter: attrs })\n  return obs\n}\n\n// Projected funding percentage for the striped preview segment. Any nonzero\n// selection paints at least a visible sliver past the fill tip, even when the\n// true share of a huge goal would round to nothing.\nfunction projectedPct(funded, goal, amount) {\n  if (!goal || goal <= 0) return 0\n  const raw = ((funded + amount) / goal) * 100\n  const floor = amount > 0 ? Math.max(raw, (funded / goal) * 100 + 0.8) : raw\n  return Math.min(100, floor)\n}\n\n// Live character counters for the /pitch wizard. Deliberately NOT Alpine:\n// LiveView step changes replace these nodes wholesale, and the clone bridge\n// can pair a fresh counter with a stale cloned component whose x-text effect\n// never re-runs. A document-level delegated listener has no per-node state\n// to go stale \u2014 it reads the wrap's data attributes at use time, every time.\nexport function installSubCounters() {\n  document.addEventListener('input', (e) => {\n    const wrap = e.target.closest && e.target.closest('.px-sub-countwrap')\n    if (!wrap) return\n    const span = wrap.querySelector('.px-sub-count')\n    if (!span) return\n\n    const n = (e.target.value || '').length\n    const min = parseInt(wrap.dataset.cmin, 10) || 0\n    const max = parseInt(wrap.dataset.cmax, 10) || 0\n\n    const low = min > 0 && n < min\n    span.textContent = low ? `${n} / ${min} minimum` : max > 0 ? `${n} / ${max}` : `${n}`\n    span.classList.toggle('px-sub-count-low', low)\n  })\n}\n\n// Modal backdrops close on a click *on the backdrop itself* (Alpine\n// `x-on:click.self`, LiveView `phx-click` on the backdrop). But when a press\n// starts inside the modal (selecting text in the email field) and the release\n// lands on the backdrop, the browser fires the click on their common ancestor \u2014\n// the backdrop \u2014 and the modal vanishes mid-typing (#620). Swallow exactly that\n// case, in the capture phase so neither Alpine nor LiveView ever sees it. A\n// press that genuinely starts on the backdrop still closes the modal.\nexport function pxModalDragGuard() {\n  let pressTarget = null\n  document.addEventListener('pointerdown', (e) => (pressTarget = e.target), true)\n  document.addEventListener(\n    'click',\n    (e) => {\n      const onBackdrop =\n        e.target instanceof Element && e.target.classList.contains('px-modal-backdrop')\n      if (onBackdrop && pressTarget !== e.target) e.stopPropagation()\n    },\n    true,\n  )\n}\n\n// Tour: tap \"?\" on the step rail. Four stops (trailer, artist, funding bar,\n// credits) and a closing \"start here\" on the dock. Each stop scrolls its\n// target into view and spotlights it with a fixed box-shadow cutout that\n// follows the target on scroll/resize; the one-line card sits below it,\n// above it, or beside it \u2014 wherever it fits.\nconst PX_TOUR_STEPS = [\n  { sel: '#px-console', mode: 'trailer', text: 'Watch what you\u2019re backing.' },\n  { sel: '#px-console', mode: 'artist', text: 'Meet the artist behind it.' },\n  { sel: '#px-hbar', text: 'Every LOOT moves this bar toward the goal.' },\n  { sel: '#px-credits-panel', text: 'Top backers get named seats in the credits.' },\n  { sel: '#px-dock', top: true, text: 'Start here. Pick an amount and go.' },\n]\n\nexport function pxTour() {\n  return {\n    open: false,\n    idx: 0,\n    steps: PX_TOUR_STEPS,\n    rect: null,\n    cardH: 120,\n    _onMove: null,\n    _raf: null,\n\n    start() {\n      if (this.open) return\n      this.idx = 0\n      this.open = true\n      this._onMove = () => {\n        if (this._raf) return\n        this._raf = requestAnimationFrame(() => {\n          this._raf = null\n          this.measure()\n        })\n      }\n      window.addEventListener('scroll', this._onMove, { passive: true })\n      window.addEventListener('resize', this._onMove)\n      this.go()\n    },\n\n    close() {\n      if (!this.open) return\n      this.open = false\n      window.removeEventListener('scroll', this._onMove)\n      window.removeEventListener('resize', this._onMove)\n      if (this._raf) cancelAnimationFrame(this._raf)\n      this._raf = null\n      window.dispatchEvent(new CustomEvent('px:console-mode', { detail: 'trailer' }))\n    },\n\n    destroy() {\n      this.close()\n    },\n\n    next() {\n      if (this.last()) return this.close()\n      this.idx += 1\n      this.go()\n    },\n\n    last() {\n      return this.idx === this.steps.length - 1\n    },\n\n    go() {\n      const step = this.steps[this.idx]\n      window.dispatchEvent(new CustomEvent('px:console-mode', { detail: step.mode || 'trailer' }))\n      const el = document.querySelector(step.sel)\n      if (!el) return this.next()\n      if (step.top) {\n        window.scrollTo({ top: 0, behavior: 'smooth' })\n      } else {\n        // Centre the target in the space left under the sticky header and\n        // dock; a target taller than that space lines up with its top.\n        const r = el.getBoundingClientRect()\n        const inset = this.topInset()\n        const room = window.innerHeight - inset\n        const offset = r.height < room ? inset + (room - r.height) / 2 : inset + 12\n        window.scrollTo({ top: window.scrollY + r.top - offset, behavior: 'smooth' })\n      }\n      this.measure()\n      this.$nextTick(() => {\n        if (this.$refs.card) this.cardH = this.$refs.card.offsetHeight\n        this.measure()\n      })\n    },\n\n    // Bottom edge of the sticky chrome (header + dock). Stops below the dock\n    // keep their spotlight and card under it rather than behind it.\n    topInset() {\n      if (this.steps[this.idx].top) return 0\n      const dock = document.querySelector('#px-dock')\n      return dock ? Math.max(0, dock.getBoundingClientRect().bottom) + 8 : 0\n    },\n\n    measure() {\n      const el = this.open && document.querySelector(this.steps[this.idx].sel)\n      if (el) this.rect = el.getBoundingClientRect()\n    },\n\n    spotStyle() {\n      const r = this.rect\n      if (!r) return 'display: none'\n      const pad = 6\n      const top = Math.max(r.top - pad, this.topInset())\n      const bottom = Math.min(r.bottom + pad, window.innerHeight)\n      return `top:${top}px;left:${r.left - pad}px;width:${r.width + pad * 2}px;height:${Math.max(bottom - top, 0)}px`\n    },\n\n    cardStyle() {\n      const r = this.rect\n      if (!r) return 'visibility: hidden'\n      const vw = window.innerWidth\n      const vh = window.innerHeight\n      const w = Math.min(300, vw - 24)\n      const gap = 14\n      const minTop = this.topInset() + 12\n      const clampX = (x) => Math.max(12, Math.min(x, vw - w - 12))\n      let top\n      let left = clampX(r.left)\n\n      if (r.bottom + gap + this.cardH < vh - 12) {\n        top = r.bottom + gap\n      } else if (r.top - gap - this.cardH > minTop) {\n        top = r.top - gap - this.cardH\n      } else if (r.left > w + gap + 12) {\n        left = r.left - gap - w\n        top = Math.max(minTop, Math.min(r.top, vh - this.cardH - 12))\n      } else {\n        top = vh - this.cardH - 12\n      }\n      return `top:${top}px;left:${left}px;width:${w}px`\n    },\n  }\n}\n", "const MediaUIEvents = {\n  MEDIA_PLAY_REQUEST: \"mediaplayrequest\",\n  MEDIA_PAUSE_REQUEST: \"mediapauserequest\",\n  MEDIA_MUTE_REQUEST: \"mediamuterequest\",\n  MEDIA_UNMUTE_REQUEST: \"mediaunmuterequest\",\n  MEDIA_VOLUME_REQUEST: \"mediavolumerequest\",\n  MEDIA_SEEK_REQUEST: \"mediaseekrequest\",\n  MEDIA_AIRPLAY_REQUEST: \"mediaairplayrequest\",\n  MEDIA_ENTER_FULLSCREEN_REQUEST: \"mediaenterfullscreenrequest\",\n  MEDIA_EXIT_FULLSCREEN_REQUEST: \"mediaexitfullscreenrequest\",\n  MEDIA_PREVIEW_REQUEST: \"mediapreviewrequest\",\n  MEDIA_ENTER_PIP_REQUEST: \"mediaenterpiprequest\",\n  MEDIA_EXIT_PIP_REQUEST: \"mediaexitpiprequest\",\n  MEDIA_ENTER_CAST_REQUEST: \"mediaentercastrequest\",\n  MEDIA_EXIT_CAST_REQUEST: \"mediaexitcastrequest\",\n  MEDIA_SHOW_TEXT_TRACKS_REQUEST: \"mediashowtexttracksrequest\",\n  MEDIA_HIDE_TEXT_TRACKS_REQUEST: \"mediahidetexttracksrequest\",\n  MEDIA_SHOW_SUBTITLES_REQUEST: \"mediashowsubtitlesrequest\",\n  MEDIA_DISABLE_SUBTITLES_REQUEST: \"mediadisablesubtitlesrequest\",\n  MEDIA_TOGGLE_SUBTITLES_REQUEST: \"mediatogglesubtitlesrequest\",\n  MEDIA_PLAYBACK_RATE_REQUEST: \"mediaplaybackraterequest\",\n  MEDIA_RENDITION_REQUEST: \"mediarenditionrequest\",\n  MEDIA_AUDIO_TRACK_REQUEST: \"mediaaudiotrackrequest\",\n  MEDIA_SEEK_TO_LIVE_REQUEST: \"mediaseektoliverequest\",\n  REGISTER_MEDIA_STATE_RECEIVER: \"registermediastatereceiver\",\n  UNREGISTER_MEDIA_STATE_RECEIVER: \"unregistermediastatereceiver\"\n};\nconst MediaStateReceiverAttributes = {\n  MEDIA_CHROME_ATTRIBUTES: \"mediachromeattributes\",\n  MEDIA_CONTROLLER: \"mediacontroller\"\n};\nconst MediaUIProps = {\n  MEDIA_AIRPLAY_UNAVAILABLE: \"mediaAirplayUnavailable\",\n  MEDIA_FULLSCREEN_UNAVAILABLE: \"mediaFullscreenUnavailable\",\n  MEDIA_PIP_UNAVAILABLE: \"mediaPipUnavailable\",\n  MEDIA_CAST_UNAVAILABLE: \"mediaCastUnavailable\",\n  MEDIA_RENDITION_UNAVAILABLE: \"mediaRenditionUnavailable\",\n  MEDIA_AUDIO_TRACK_UNAVAILABLE: \"mediaAudioTrackUnavailable\",\n  MEDIA_WIDTH: \"mediaWidth\",\n  MEDIA_HEIGHT: \"mediaHeight\",\n  MEDIA_PAUSED: \"mediaPaused\",\n  MEDIA_HAS_PLAYED: \"mediaHasPlayed\",\n  MEDIA_ENDED: \"mediaEnded\",\n  MEDIA_MUTED: \"mediaMuted\",\n  MEDIA_VOLUME_LEVEL: \"mediaVolumeLevel\",\n  MEDIA_VOLUME: \"mediaVolume\",\n  MEDIA_VOLUME_UNAVAILABLE: \"mediaVolumeUnavailable\",\n  MEDIA_IS_PIP: \"mediaIsPip\",\n  MEDIA_IS_CASTING: \"mediaIsCasting\",\n  MEDIA_IS_AIRPLAYING: \"mediaIsAirplaying\",\n  MEDIA_SUBTITLES_LIST: \"mediaSubtitlesList\",\n  MEDIA_SUBTITLES_SHOWING: \"mediaSubtitlesShowing\",\n  MEDIA_IS_FULLSCREEN: \"mediaIsFullscreen\",\n  MEDIA_PLAYBACK_RATE: \"mediaPlaybackRate\",\n  MEDIA_CURRENT_TIME: \"mediaCurrentTime\",\n  MEDIA_DURATION: \"mediaDuration\",\n  MEDIA_SEEKABLE: \"mediaSeekable\",\n  MEDIA_PREVIEW_TIME: \"mediaPreviewTime\",\n  MEDIA_PREVIEW_IMAGE: \"mediaPreviewImage\",\n  MEDIA_PREVIEW_COORDS: \"mediaPreviewCoords\",\n  MEDIA_PREVIEW_CHAPTER: \"mediaPreviewChapter\",\n  MEDIA_LOADING: \"mediaLoading\",\n  MEDIA_BUFFERED: \"mediaBuffered\",\n  MEDIA_STREAM_TYPE: \"mediaStreamType\",\n  MEDIA_TARGET_LIVE_WINDOW: \"mediaTargetLiveWindow\",\n  MEDIA_TIME_IS_LIVE: \"mediaTimeIsLive\",\n  MEDIA_RENDITION_LIST: \"mediaRenditionList\",\n  MEDIA_RENDITION_SELECTED: \"mediaRenditionSelected\",\n  MEDIA_AUDIO_TRACK_LIST: \"mediaAudioTrackList\",\n  MEDIA_AUDIO_TRACK_ENABLED: \"mediaAudioTrackEnabled\",\n  MEDIA_CHAPTERS_CUES: \"mediaChaptersCues\"\n};\nconst MediaUIPropsEntries = Object.entries(\n  MediaUIProps\n);\nconst MediaUIAttributes = MediaUIPropsEntries.reduce(\n  (dictObj, [key, propName]) => {\n    dictObj[key] = propName.toLowerCase();\n    return dictObj;\n  },\n  {}\n);\nconst AdditionalStateChangeEvents = {\n  USER_INACTIVE: \"userinactivechange\",\n  BREAKPOINTS_CHANGE: \"breakpointchange\",\n  BREAKPOINTS_COMPUTED: \"breakpointscomputed\"\n};\nconst MediaStateChangeEvents = MediaUIPropsEntries.reduce(\n  (dictObj, [key, propName]) => {\n    dictObj[key] = propName.toLowerCase();\n    return dictObj;\n  },\n  { ...AdditionalStateChangeEvents }\n);\nconst StateChangeEventToAttributeMap = Object.entries(\n  MediaStateChangeEvents\n).reduce(\n  (mapObj, [key, eventType]) => {\n    const attrName = MediaUIAttributes[key];\n    if (attrName) {\n      mapObj[eventType] = attrName;\n    }\n    return mapObj;\n  },\n  { userinactivechange: \"userinactive\" }\n);\nconst AttributeToStateChangeEventMap = Object.entries(\n  MediaUIAttributes\n).reduce(\n  (mapObj, [key, attrName]) => {\n    const evtType = MediaStateChangeEvents[key];\n    if (evtType) {\n      mapObj[attrName] = evtType;\n    }\n    return mapObj;\n  },\n  { userinactive: \"userinactivechange\" }\n);\nconst TextTrackKinds = {\n  SUBTITLES: \"subtitles\",\n  CAPTIONS: \"captions\",\n  DESCRIPTIONS: \"descriptions\",\n  CHAPTERS: \"chapters\",\n  METADATA: \"metadata\"\n};\nconst TextTrackModes = {\n  DISABLED: \"disabled\",\n  HIDDEN: \"hidden\",\n  SHOWING: \"showing\"\n};\nconst ReadyStates = {\n  HAVE_NOTHING: 0,\n  HAVE_METADATA: 1,\n  HAVE_CURRENT_DATA: 2,\n  HAVE_FUTURE_DATA: 3,\n  HAVE_ENOUGH_DATA: 4\n};\nconst PointerTypes = {\n  MOUSE: \"mouse\",\n  PEN: \"pen\",\n  TOUCH: \"touch\"\n};\nconst AvailabilityStates = {\n  UNAVAILABLE: \"unavailable\",\n  UNSUPPORTED: \"unsupported\"\n};\nconst StreamTypes = {\n  LIVE: \"live\",\n  ON_DEMAND: \"on-demand\",\n  UNKNOWN: \"unknown\"\n};\nconst VolumeLevels = {\n  HIGH: \"high\",\n  MEDIUM: \"medium\",\n  LOW: \"low\",\n  OFF: \"off\"\n};\nconst WebkitPresentationModes = {\n  INLINE: \"inline\",\n  FULLSCREEN: \"fullscreen\",\n  PICTURE_IN_PICTURE: \"picture-in-picture\"\n};\nexport {\n  AttributeToStateChangeEventMap,\n  AvailabilityStates,\n  MediaStateChangeEvents,\n  MediaStateReceiverAttributes,\n  MediaUIAttributes,\n  MediaUIEvents,\n  MediaUIProps,\n  PointerTypes,\n  ReadyStates,\n  StateChangeEventToAttributeMap,\n  StreamTypes,\n  TextTrackKinds,\n  TextTrackModes,\n  VolumeLevels,\n  WebkitPresentationModes\n};\n", "const tooltipLabels = {\n  ENTER_AIRPLAY: \"Start airplay\",\n  EXIT_AIRPLAY: \"Stop airplay\",\n  AUDIO_TRACK_MENU: \"Audio\",\n  CAPTIONS: \"Captions\",\n  ENABLE_CAPTIONS: \"Enable captions\",\n  DISABLE_CAPTIONS: \"Disable captions\",\n  START_CAST: \"Start casting\",\n  STOP_CAST: \"Stop casting\",\n  ENTER_FULLSCREEN: \"Enter fullscreen mode\",\n  EXIT_FULLSCREEN: \"Exit fullscreen mode\",\n  MUTE: \"Mute\",\n  UNMUTE: \"Unmute\",\n  ENTER_PIP: \"Enter picture in picture mode\",\n  EXIT_PIP: \"Enter picture in picture mode\",\n  PLAY: \"Play\",\n  PAUSE: \"Pause\",\n  PLAYBACK_RATE: \"Playback rate\",\n  RENDITIONS: \"Quality\",\n  SEEK_BACKWARD: \"Seek backward\",\n  SEEK_FORWARD: \"Seek forward\",\n  SETTINGS: \"Settings\"\n};\nconst nouns = {\n  AUDIO_PLAYER: () => \"audio player\",\n  VIDEO_PLAYER: () => \"video player\",\n  VOLUME: () => \"volume\",\n  SEEK: () => \"seek\",\n  CLOSED_CAPTIONS: () => \"closed captions\",\n  PLAYBACK_RATE: ({ playbackRate = 1 } = {}) => `current playback rate ${playbackRate}`,\n  PLAYBACK_TIME: () => `playback time`,\n  MEDIA_LOADING: () => `media loading`,\n  SETTINGS: () => `settings`,\n  AUDIO_TRACKS: () => `audio tracks`,\n  QUALITY: () => `quality`\n};\nconst verbs = {\n  PLAY: () => \"play\",\n  PAUSE: () => \"pause\",\n  MUTE: () => \"mute\",\n  UNMUTE: () => \"unmute\",\n  ENTER_AIRPLAY: () => \"start airplay\",\n  EXIT_AIRPLAY: () => \"stop airplay\",\n  ENTER_CAST: () => \"start casting\",\n  EXIT_CAST: () => \"stop casting\",\n  ENTER_FULLSCREEN: () => \"enter fullscreen mode\",\n  EXIT_FULLSCREEN: () => \"exit fullscreen mode\",\n  ENTER_PIP: () => \"enter picture in picture mode\",\n  EXIT_PIP: () => \"exit picture in picture mode\",\n  SEEK_FORWARD_N_SECS: ({ seekOffset = 30 } = {}) => `seek forward ${seekOffset} seconds`,\n  SEEK_BACK_N_SECS: ({ seekOffset = 30 } = {}) => `seek back ${seekOffset} seconds`,\n  SEEK_LIVE: () => \"seek to live\",\n  PLAYING_LIVE: () => \"playing live\"\n};\nvar labels_default = {\n  ...nouns,\n  ...verbs\n};\nexport {\n  labels_default as default,\n  nouns,\n  tooltipLabels,\n  verbs\n};\n", "function stringifyRenditionList(renditions) {\n  return renditions == null ? void 0 : renditions.map(stringifyRendition).join(\" \");\n}\nfunction parseRenditionList(renditions) {\n  return renditions == null ? void 0 : renditions.split(/\\s+/).map(parseRendition);\n}\nfunction stringifyRendition(rendition) {\n  if (rendition) {\n    const { id, width, height } = rendition;\n    return [id, width, height].filter((a) => a != null).join(\":\");\n  }\n}\nfunction parseRendition(rendition) {\n  if (rendition) {\n    const [id, width, height] = rendition.split(\":\");\n    return { id, width: +width, height: +height };\n  }\n}\nfunction stringifyAudioTrackList(audioTracks) {\n  return audioTracks == null ? void 0 : audioTracks.map(stringifyAudioTrack).join(\" \");\n}\nfunction parseAudioTrackList(audioTracks) {\n  return audioTracks == null ? void 0 : audioTracks.split(/\\s+/).map(parseAudioTrack);\n}\nfunction stringifyAudioTrack(audioTrack) {\n  if (audioTrack) {\n    const { id, kind, language, label } = audioTrack;\n    return [id, kind, language, label].filter((a) => a != null).join(\":\");\n  }\n}\nfunction parseAudioTrack(audioTrack) {\n  if (audioTrack) {\n    const [id, kind, language, label] = audioTrack.split(\":\");\n    return {\n      id,\n      kind,\n      language,\n      label\n    };\n  }\n}\nfunction dashedToCamel(word) {\n  return word.split(\"-\").map(function(x, i) {\n    return (i ? x[0].toUpperCase() : x[0].toLowerCase()) + x.slice(1).toLowerCase();\n  }).join(\"\");\n}\nfunction constToCamel(word, upperFirst = false) {\n  return word.split(\"_\").map(function(x, i) {\n    return (i || upperFirst ? x[0].toUpperCase() : x[0].toLowerCase()) + x.slice(1).toLowerCase();\n  }).join(\"\");\n}\nfunction camelCase(name) {\n  return name.replace(/[-_]([a-z])/g, ($0, $1) => $1.toUpperCase());\n}\nfunction isValidNumber(x) {\n  return typeof x === \"number\" && !Number.isNaN(x) && Number.isFinite(x);\n}\nfunction isNumericString(str) {\n  if (typeof str != \"string\")\n    return false;\n  return !isNaN(str) && !isNaN(parseFloat(str));\n}\nconst delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));\nconst capitalize = (str) => str && str[0].toUpperCase() + str.slice(1);\nexport {\n  camelCase,\n  capitalize,\n  constToCamel,\n  dashedToCamel,\n  delay,\n  isNumericString,\n  isValidNumber,\n  parseAudioTrack,\n  parseAudioTrackList,\n  parseRendition,\n  parseRenditionList,\n  stringifyAudioTrack,\n  stringifyAudioTrackList,\n  stringifyRendition,\n  stringifyRenditionList\n};\n", "import { isValidNumber } from \"./utils.js\";\nconst UnitLabels = [\n  {\n    singular: \"hour\",\n    plural: \"hours\"\n  },\n  {\n    singular: \"minute\",\n    plural: \"minutes\"\n  },\n  {\n    singular: \"second\",\n    plural: \"seconds\"\n  }\n];\nconst toTimeUnitPhrase = (timeUnitValue, unitIndex) => {\n  const unitLabel = timeUnitValue === 1 ? UnitLabels[unitIndex].singular : UnitLabels[unitIndex].plural;\n  return `${timeUnitValue} ${unitLabel}`;\n};\nconst formatAsTimePhrase = (seconds) => {\n  if (!isValidNumber(seconds))\n    return \"\";\n  const positiveSeconds = Math.abs(seconds);\n  const negative = positiveSeconds !== seconds;\n  const secondsDateTime = new Date(0, 0, 0, 0, 0, positiveSeconds, 0);\n  const timeParts = [\n    secondsDateTime.getHours(),\n    secondsDateTime.getMinutes(),\n    secondsDateTime.getSeconds()\n  ];\n  const timeString = timeParts.map(\n    (timeUnitValue, index) => timeUnitValue && toTimeUnitPhrase(timeUnitValue, index)\n  ).filter((x) => x).join(\", \");\n  const negativeSuffix = negative ? \" remaining\" : \"\";\n  return `${timeString}${negativeSuffix}`;\n};\nfunction formatTime(seconds, guide) {\n  let negative = false;\n  if (seconds < 0) {\n    negative = true;\n    seconds = 0 - seconds;\n  }\n  seconds = seconds < 0 ? 0 : seconds;\n  let s = Math.floor(seconds % 60);\n  let m = Math.floor(seconds / 60 % 60);\n  let h = Math.floor(seconds / 3600);\n  const gm = Math.floor(guide / 60 % 60);\n  const gh = Math.floor(guide / 3600);\n  if (isNaN(seconds) || seconds === Infinity) {\n    h = m = s = \"0\";\n  }\n  h = h > 0 || gh > 0 ? h + \":\" : \"\";\n  m = ((h || gm >= 10) && m < 10 ? \"0\" + m : m) + \":\";\n  s = s < 10 ? \"0\" + s : s;\n  return (negative ? \"-\" : \"\") + h + m + s;\n}\nconst emptyTimeRanges = Object.freeze({\n  length: 0,\n  start(index) {\n    const unsignedIdx = index >>> 0;\n    if (unsignedIdx >= this.length) {\n      throw new DOMException(\n        `Failed to execute 'start' on 'TimeRanges': The index provided (${unsignedIdx}) is greater than or equal to the maximum bound (${this.length}).`\n      );\n    }\n    return 0;\n  },\n  end(index) {\n    const unsignedIdx = index >>> 0;\n    if (unsignedIdx >= this.length) {\n      throw new DOMException(\n        `Failed to execute 'end' on 'TimeRanges': The index provided (${unsignedIdx}) is greater than or equal to the maximum bound (${this.length}).`\n      );\n    }\n    return 0;\n  }\n});\nfunction serializeTimeRanges(timeRanges = emptyTimeRanges) {\n  return Array.from(timeRanges).map(\n    (_, i) => [\n      Number(timeRanges.start(i).toFixed(3)),\n      Number(timeRanges.end(i).toFixed(3))\n    ].join(\":\")\n  ).join(\" \");\n}\nexport {\n  emptyTimeRanges,\n  formatAsTimePhrase,\n  formatTime,\n  serializeTimeRanges\n};\n", "class EventTarget {\n  addEventListener() {\n  }\n  removeEventListener() {\n  }\n  dispatchEvent() {\n    return true;\n  }\n}\nclass Node extends EventTarget {\n}\nclass Element extends Node {\n  constructor() {\n    super(...arguments);\n    this.role = null;\n  }\n}\nclass ResizeObserver {\n  observe() {\n  }\n  unobserve() {\n  }\n  disconnect() {\n  }\n}\nconst documentShim = {\n  createElement: function() {\n    return new globalThisShim.HTMLElement();\n  },\n  createElementNS: function() {\n    return new globalThisShim.HTMLElement();\n  },\n  addEventListener() {\n  },\n  removeEventListener() {\n  },\n  /**\n   *\n   * @param {Event} event\n   * @returns {boolean}\n   */\n  dispatchEvent(event) {\n    return false;\n  }\n};\nconst globalThisShim = {\n  ResizeObserver,\n  document: documentShim,\n  Node,\n  Element,\n  HTMLElement: class HTMLElement extends Element {\n    constructor() {\n      super(...arguments);\n      this.innerHTML = \"\";\n    }\n    get content() {\n      return new globalThisShim.DocumentFragment();\n    }\n  },\n  DocumentFragment: class DocumentFragment extends EventTarget {\n  },\n  customElements: {\n    get: function() {\n    },\n    define: function() {\n    },\n    whenDefined: function() {\n    }\n  },\n  localStorage: {\n    /**\n     * @param {string} key\n     * @returns {string|null}\n     */\n    getItem(key) {\n      return null;\n    },\n    /**\n     * @param {string} key\n     * @param {string} value\n     */\n    setItem(key, value) {\n    },\n    // eslint-disable-line @typescript-eslint/no-unused-vars\n    /**\n     * @param {string} key\n     */\n    removeItem(key) {\n    }\n    // eslint-disable-line @typescript-eslint/no-unused-vars\n  },\n  CustomEvent: function CustomEvent() {\n  },\n  getComputedStyle: function() {\n  },\n  navigator: {\n    languages: [],\n    get userAgent() {\n      return \"\";\n    }\n  },\n  /**\n   * @param {string} media\n   */\n  matchMedia(media) {\n    return {\n      matches: false,\n      media\n    };\n  }\n};\nconst isServer = typeof window === \"undefined\" || typeof window.customElements === \"undefined\";\nconst isShimmed = Object.keys(globalThisShim).every((key) => key in globalThis);\nconst GlobalThis = isServer && !isShimmed ? globalThisShim : globalThis;\nconst Document = isServer && !isShimmed ? documentShim : globalThis.document;\nexport {\n  Document,\n  GlobalThis,\n  Document as document,\n  GlobalThis as globalThis,\n  isServer\n};\n", "import { globalThis } from \"./server-safe-globals.js\";\nconst callbacksMap = /* @__PURE__ */ new WeakMap();\nconst getCallbacks = (element) => {\n  let callbacks = callbacksMap.get(element);\n  if (!callbacks)\n    callbacksMap.set(element, callbacks = /* @__PURE__ */ new Set());\n  return callbacks;\n};\nconst observer = new globalThis.ResizeObserver(\n  (entries) => {\n    for (const entry of entries) {\n      for (const callback of getCallbacks(entry.target)) {\n        callback(entry);\n      }\n    }\n  }\n);\nfunction observeResize(element, callback) {\n  getCallbacks(element).add(callback);\n  observer.observe(element);\n}\nfunction unobserveResize(element, callback) {\n  const callbacks = getCallbacks(element);\n  callbacks.delete(callback);\n  if (!callbacks.size) {\n    observer.unobserve(element);\n  }\n}\nexport {\n  observeResize,\n  unobserveResize\n};\n", "import { MediaStateReceiverAttributes } from \"../constants.js\";\nfunction getMediaController(host) {\n  var _a;\n  return (_a = getAttributeMediaController(host)) != null ? _a : closestComposedNode(host, \"media-controller\");\n}\nfunction getAttributeMediaController(host) {\n  var _a;\n  const { MEDIA_CONTROLLER } = MediaStateReceiverAttributes;\n  const mediaControllerId = host.getAttribute(MEDIA_CONTROLLER);\n  if (mediaControllerId) {\n    return (_a = getDocumentOrShadowRoot(host)) == null ? void 0 : _a.getElementById(\n      mediaControllerId\n    );\n  }\n}\nconst updateIconText = (svg, value, selector = \".value\") => {\n  const node = svg.querySelector(selector);\n  if (!node)\n    return;\n  node.textContent = value;\n};\nconst getAllSlotted = (el, name) => {\n  const slotSelector = `slot[name=\"${name}\"]`;\n  const slot = el.shadowRoot.querySelector(slotSelector);\n  if (!slot)\n    return [];\n  return slot.children;\n};\nconst getSlotted = (el, name) => getAllSlotted(el, name)[0];\nconst containsComposedNode = (rootNode, childNode) => {\n  if (!rootNode || !childNode)\n    return false;\n  if (rootNode == null ? void 0 : rootNode.contains(childNode))\n    return true;\n  return containsComposedNode(\n    rootNode,\n    childNode.getRootNode().host\n  );\n};\nconst closestComposedNode = (childNode, selector) => {\n  if (!childNode)\n    return null;\n  const closest = childNode.closest(selector);\n  if (closest)\n    return closest;\n  return closestComposedNode(\n    childNode.getRootNode().host,\n    selector\n  );\n};\nfunction getActiveElement(root = document) {\n  var _a;\n  const activeEl = root == null ? void 0 : root.activeElement;\n  if (!activeEl)\n    return null;\n  return (_a = getActiveElement(activeEl.shadowRoot)) != null ? _a : activeEl;\n}\nfunction getDocumentOrShadowRoot(node) {\n  var _a;\n  const rootNode = (_a = node == null ? void 0 : node.getRootNode) == null ? void 0 : _a.call(node);\n  if (rootNode instanceof ShadowRoot || rootNode instanceof Document) {\n    return rootNode;\n  }\n  return null;\n}\nfunction isElementVisible(element, depth = 3) {\n  if (element.checkVisibility) {\n    return element.checkVisibility({\n      checkOpacity: true,\n      checkVisibilityCSS: true\n    });\n  }\n  let el = element;\n  while (el && depth > 0) {\n    const style = getComputedStyle(el);\n    if (style.opacity === \"0\" || style.visibility === \"hidden\" || style.display === \"none\") {\n      return false;\n    }\n    el = el.parentElement;\n    depth--;\n  }\n  return true;\n}\nfunction getPointProgressOnLine(x, y, p1, p2) {\n  const segment = distance(p1, p2);\n  const toStart = distance(p1, { x, y });\n  const toEnd = distance(p2, { x, y });\n  if (toStart > segment || toEnd > segment) {\n    return toStart > toEnd ? 1 : 0;\n  }\n  return toStart / segment;\n}\nfunction distance(p1, p2) {\n  return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));\n}\nfunction getOrInsertCSSRule(styleParent, selectorText) {\n  const cssRule = getCSSRule(styleParent, (st) => st === selectorText);\n  if (cssRule)\n    return cssRule;\n  return insertCSSRule(styleParent, selectorText);\n}\nfunction getCSSRule(styleParent, predicate) {\n  var _a, _b;\n  let style;\n  for (style of (_a = styleParent.querySelectorAll(\"style:not([media])\")) != null ? _a : []) {\n    let cssRules;\n    try {\n      cssRules = (_b = style.sheet) == null ? void 0 : _b.cssRules;\n    } catch {\n      continue;\n    }\n    for (const rule of cssRules != null ? cssRules : []) {\n      if (predicate(rule.selectorText))\n        return rule;\n    }\n  }\n}\nfunction insertCSSRule(styleParent, selectorText) {\n  var _a, _b;\n  const styles = (_a = styleParent.querySelectorAll(\"style:not([media])\")) != null ? _a : [];\n  const style = styles == null ? void 0 : styles[styles.length - 1];\n  if (!(style == null ? void 0 : style.sheet)) {\n    console.warn(\n      \"Media Chrome: No style sheet found on style tag of\",\n      styleParent\n    );\n    return {\n      // @ts-ignore\n      style: {\n        setProperty: () => {\n        },\n        removeProperty: () => \"\",\n        getPropertyValue: () => \"\"\n      }\n    };\n  }\n  style == null ? void 0 : style.sheet.insertRule(`${selectorText}{}`, style.sheet.cssRules.length);\n  return (\n    /** @type {CSSStyleRule} */\n    (_b = style.sheet.cssRules) == null ? void 0 : _b[style.sheet.cssRules.length - 1]\n  );\n}\nfunction getNumericAttr(el, attrName, defaultValue = Number.NaN) {\n  const attrVal = el.getAttribute(attrName);\n  return attrVal != null ? +attrVal : defaultValue;\n}\nfunction setNumericAttr(el, attrName, value) {\n  const nextNumericValue = +value;\n  if (value == null || Number.isNaN(nextNumericValue)) {\n    if (el.hasAttribute(attrName)) {\n      el.removeAttribute(attrName);\n    }\n    return;\n  }\n  if (getNumericAttr(el, attrName, void 0) === nextNumericValue)\n    return;\n  el.setAttribute(attrName, `${nextNumericValue}`);\n}\nfunction getBooleanAttr(el, attrName) {\n  return el.hasAttribute(attrName);\n}\nfunction setBooleanAttr(el, attrName, value) {\n  if (value == null) {\n    if (el.hasAttribute(attrName)) {\n      el.removeAttribute(attrName);\n    }\n    return;\n  }\n  if (getBooleanAttr(el, attrName) == value)\n    return;\n  el.toggleAttribute(attrName, value);\n}\nfunction getStringAttr(el, attrName, defaultValue = null) {\n  var _a;\n  return (_a = el.getAttribute(attrName)) != null ? _a : defaultValue;\n}\nfunction setStringAttr(el, attrName, value) {\n  if (value == null) {\n    if (el.hasAttribute(attrName)) {\n      el.removeAttribute(attrName);\n    }\n    return;\n  }\n  const nextValue = `${value}`;\n  if (getStringAttr(el, attrName, void 0) === nextValue)\n    return;\n  el.setAttribute(attrName, nextValue);\n}\nexport {\n  closestComposedNode,\n  containsComposedNode,\n  distance,\n  getActiveElement,\n  getAllSlotted,\n  getAttributeMediaController,\n  getBooleanAttr,\n  getCSSRule,\n  getDocumentOrShadowRoot,\n  getMediaController,\n  getNumericAttr,\n  getOrInsertCSSRule,\n  getPointProgressOnLine,\n  getSlotted,\n  getStringAttr,\n  insertCSSRule,\n  isElementVisible,\n  setBooleanAttr,\n  setNumericAttr,\n  setStringAttr,\n  updateIconText\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar __privateSet = (obj, member, value, setter) => {\n  __accessCheck(obj, member, \"write to private field\");\n  setter ? setter.call(obj, value) : member.set(obj, value);\n  return value;\n};\nvar _mediaController;\nimport {\n  MediaUIAttributes,\n  MediaUIEvents,\n  MediaStateReceiverAttributes,\n  PointerTypes\n} from \"./constants.js\";\nimport {\n  closestComposedNode,\n  getBooleanAttr,\n  setBooleanAttr\n} from \"./utils/element-utils.js\";\nimport { globalThis, document } from \"./utils/server-safe-globals.js\";\nconst template = document.createElement(\"template\");\ntemplate.innerHTML = /*html*/\n`\n<style>\n  :host {\n    display: var(--media-control-display, var(--media-gesture-receiver-display, inline-block));\n    box-sizing: border-box;\n  }\n</style>\n`;\nclass MediaGestureReceiver extends globalThis.HTMLElement {\n  constructor(options = {}) {\n    super();\n    __privateAdd(this, _mediaController, void 0);\n    if (!this.shadowRoot) {\n      const shadow = this.attachShadow({ mode: \"open\" });\n      const buttonHTML = template.content.cloneNode(true);\n      this.nativeEl = buttonHTML;\n      let slotTemplate = options.slotTemplate;\n      if (!slotTemplate) {\n        slotTemplate = document.createElement(\"template\");\n        slotTemplate.innerHTML = `<slot>${options.defaultContent || \"\"}</slot>`;\n      }\n      this.nativeEl.appendChild(slotTemplate.content.cloneNode(true));\n      shadow.appendChild(buttonHTML);\n    }\n  }\n  // NOTE: Currently \"baking in\" actions + attrs until we come up with\n  // a more robust architecture (CJP)\n  static get observedAttributes() {\n    return [\n      MediaStateReceiverAttributes.MEDIA_CONTROLLER,\n      MediaUIAttributes.MEDIA_PAUSED\n    ];\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    var _a, _b, _c, _d, _e;\n    if (attrName === MediaStateReceiverAttributes.MEDIA_CONTROLLER) {\n      if (oldValue) {\n        (_b = (_a = __privateGet(this, _mediaController)) == null ? void 0 : _a.unassociateElement) == null ? void 0 : _b.call(_a, this);\n        __privateSet(this, _mediaController, null);\n      }\n      if (newValue && this.isConnected) {\n        __privateSet(this, _mediaController, (_c = this.getRootNode()) == null ? void 0 : _c.getElementById(newValue));\n        (_e = (_d = __privateGet(this, _mediaController)) == null ? void 0 : _d.associateElement) == null ? void 0 : _e.call(_d, this);\n      }\n    }\n  }\n  connectedCallback() {\n    var _a, _b, _c, _d;\n    this.tabIndex = -1;\n    this.setAttribute(\"aria-hidden\", \"true\");\n    __privateSet(this, _mediaController, getMediaControllerEl(this));\n    if (this.getAttribute(MediaStateReceiverAttributes.MEDIA_CONTROLLER)) {\n      (_b = (_a = __privateGet(this, _mediaController)) == null ? void 0 : _a.associateElement) == null ? void 0 : _b.call(_a, this);\n    }\n    (_c = __privateGet(this, _mediaController)) == null ? void 0 : _c.addEventListener(\"pointerdown\", this);\n    (_d = __privateGet(this, _mediaController)) == null ? void 0 : _d.addEventListener(\"click\", this);\n  }\n  disconnectedCallback() {\n    var _a, _b, _c, _d;\n    if (this.getAttribute(MediaStateReceiverAttributes.MEDIA_CONTROLLER)) {\n      (_b = (_a = __privateGet(this, _mediaController)) == null ? void 0 : _a.unassociateElement) == null ? void 0 : _b.call(_a, this);\n    }\n    (_c = __privateGet(this, _mediaController)) == null ? void 0 : _c.removeEventListener(\"pointerdown\", this);\n    (_d = __privateGet(this, _mediaController)) == null ? void 0 : _d.removeEventListener(\"click\", this);\n    __privateSet(this, _mediaController, null);\n  }\n  handleEvent(event) {\n    var _a;\n    const composedTarget = (_a = event.composedPath()) == null ? void 0 : _a[0];\n    const allowList = [\"video\", \"media-controller\"];\n    if (!allowList.includes(composedTarget == null ? void 0 : composedTarget.localName))\n      return;\n    if (event.type === \"pointerdown\") {\n      this._pointerType = event.pointerType;\n    } else if (event.type === \"click\") {\n      const { clientX, clientY } = event;\n      const { left, top, width, height } = this.getBoundingClientRect();\n      const x = clientX - left;\n      const y = clientY - top;\n      if (x < 0 || y < 0 || x > width || y > height || // In case this element has no dimensions (or display: none) return.\n      width === 0 && height === 0) {\n        return;\n      }\n      const { pointerType = this._pointerType } = event;\n      this._pointerType = void 0;\n      if (pointerType === PointerTypes.TOUCH) {\n        this.handleTap(event);\n        return;\n      } else if (pointerType === PointerTypes.MOUSE) {\n        this.handleMouseClick(event);\n        return;\n      }\n    }\n  }\n  /**\n   * @type {boolean} Is the media paused\n   */\n  get mediaPaused() {\n    return getBooleanAttr(this, MediaUIAttributes.MEDIA_PAUSED);\n  }\n  set mediaPaused(value) {\n    setBooleanAttr(this, MediaUIAttributes.MEDIA_PAUSED, value);\n  }\n  // NOTE: Currently \"baking in\" actions + attrs until we come up with\n  // a more robust architecture (CJP)\n  /**\n   * @abstract\n   * @argument {Event} e\n   */\n  handleTap(e) {\n  }\n  // eslint-disable-line\n  // eslint-disable-next-line\n  handleMouseClick(e) {\n    const eventName = this.mediaPaused ? MediaUIEvents.MEDIA_PLAY_REQUEST : MediaUIEvents.MEDIA_PAUSE_REQUEST;\n    this.dispatchEvent(\n      new globalThis.CustomEvent(eventName, { composed: true, bubbles: true })\n    );\n  }\n}\n_mediaController = new WeakMap();\nfunction getMediaControllerEl(controlEl) {\n  var _a;\n  const mediaControllerId = controlEl.getAttribute(\n    MediaStateReceiverAttributes.MEDIA_CONTROLLER\n  );\n  if (mediaControllerId) {\n    return (_a = controlEl.getRootNode()) == null ? void 0 : _a.getElementById(mediaControllerId);\n  }\n  return closestComposedNode(controlEl, \"media-controller\");\n}\nif (!globalThis.customElements.get(\"media-gesture-receiver\")) {\n  globalThis.customElements.define(\n    \"media-gesture-receiver\",\n    MediaGestureReceiver\n  );\n}\nvar media_gesture_receiver_default = MediaGestureReceiver;\nexport {\n  media_gesture_receiver_default as default\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar __privateSet = (obj, member, value, setter) => {\n  __accessCheck(obj, member, \"write to private field\");\n  setter ? setter.call(obj, value) : member.set(obj, value);\n  return value;\n};\nvar __privateMethod = (obj, member, method) => {\n  __accessCheck(obj, member, \"access private method\");\n  return method;\n};\nvar _pointerDownTimeStamp, _currentMedia, _inactiveTimeout, _autohide, _handlePointerMove, handlePointerMove_fn, _handlePointerUp, handlePointerUp_fn, _setInactive, setInactive_fn, _setActive, setActive_fn, _scheduleInactive, scheduleInactive_fn;\nimport { globalThis, document } from \"./utils/server-safe-globals.js\";\nimport { MediaUIAttributes, MediaStateChangeEvents } from \"./constants.js\";\nimport { nouns } from \"./labels/labels.js\";\nimport { observeResize } from \"./utils/resize-observer.js\";\nimport \"./media-gesture-receiver.js\";\nconst Attributes = {\n  AUDIO: \"audio\",\n  AUTOHIDE: \"autohide\",\n  BREAKPOINTS: \"breakpoints\",\n  GESTURES_DISABLED: \"gesturesdisabled\",\n  KEYBOARD_CONTROL: \"keyboardcontrol\",\n  NO_AUTOHIDE: \"noautohide\",\n  USER_INACTIVE: \"userinactive\"\n};\nconst template = document.createElement(\"template\");\ntemplate.innerHTML = /*html*/\n`\n  <style>\n    ${/*\n * outline on media is turned off because it is allowed to get focus to faciliate hotkeys.\n * However, on keyboard interactions, the focus outline is shown,\n * which is particularly noticeable when going fullscreen via hotkeys.\n */\n\"\"}\n    :host([${MediaUIAttributes.MEDIA_IS_FULLSCREEN}]) ::slotted([slot=media]) {\n      outline: none;\n    }\n\n    :host {\n      box-sizing: border-box;\n      position: relative;\n      display: inline-block;\n      line-height: 0;\n      background-color: var(--media-background-color, #000);\n    }\n\n    :host(:not([${Attributes.AUDIO}])) [part~=layer]:not([part~=media-layer]) {\n      position: absolute;\n      top: 0;\n      left: 0;\n      bottom: 0;\n      right: 0;\n      display: flex;\n      flex-flow: column nowrap;\n      align-items: start;\n      pointer-events: none;\n      background: none;\n    }\n\n    slot[name=media] {\n      display: var(--media-slot-display, contents);\n    }\n\n    ${/*\n * when in audio mode, hide the slotted media element by default\n */\n\"\"}\n    :host([${Attributes.AUDIO}]) slot[name=media] {\n      display: var(--media-slot-display, none);\n    }\n\n    ${/*\n * when in audio mode, hide the gesture-layer which causes media-controller to be taller than the control bar\n */\n\"\"}\n    :host([${Attributes.AUDIO}]) [part~=layer][part~=gesture-layer] {\n      height: 0;\n      display: block;\n    }\n\n    ${/*\n * if gestures are disabled, don't accept pointer-events\n */\n\"\"}\n    :host(:not([${Attributes.AUDIO}])[${Attributes.GESTURES_DISABLED}]) ::slotted([slot=gestures-chrome]),\n    :host(:not([${Attributes.AUDIO}])[${Attributes.GESTURES_DISABLED}]) media-gesture-receiver[slot=gestures-chrome] {\n      display: none;\n    }\n\n    ${/*\n * any slotted element that isn't a poster or media slot should be pointer-events auto\n * we'll want to add here any slotted elements that shouldn't get pointer-events by default when slotted\n */\n\"\"}\n    ::slotted(:not([slot=media]):not([slot=poster]):not(media-loading-indicator):not([hidden])) {\n      pointer-events: auto;\n    }\n\n    :host(:not([${Attributes.AUDIO}])) *[part~=layer][part~=centered-layer] {\n      align-items: center;\n      justify-content: center;\n    }\n\n    :host(:not([${Attributes.AUDIO}])) ::slotted(media-gesture-receiver[slot=gestures-chrome]),\n    :host(:not([${Attributes.AUDIO}])) media-gesture-receiver[slot=gestures-chrome] {\n      align-self: stretch;\n      flex-grow: 1;\n    }\n\n    slot[name=middle-chrome] {\n      display: inline;\n      flex-grow: 1;\n      pointer-events: none;\n      background: none;\n    }\n\n    ${/* Position the media and poster elements to fill the container */\n\"\"}\n    ::slotted([slot=media]),\n    ::slotted([slot=poster]) {\n      width: 100%;\n      height: 100%;\n    }\n\n    ${/* Video specific styles */\n\"\"}\n    :host(:not([${Attributes.AUDIO}])) .spacer {\n      flex-grow: 1;\n    }\n\n    ${/* Safari needs this to actually make the element fill the window */\n\"\"}\n    :host(:-webkit-full-screen) {\n      ${/* Needs to use !important otherwise easy to break */\n\"\"}\n      width: 100% !important;\n      height: 100% !important;\n    }\n\n    ${/* Only add these if auto hide is not disabled */\n\"\"}\n    ::slotted(:not([slot=media]):not([slot=poster]):not([${Attributes.NO_AUTOHIDE}]):not([hidden])) {\n      opacity: 1;\n      transition: opacity 0.25s;\n    }\n\n    ${/* Hide controls when inactive, not paused, not audio and auto hide not disabled */\n\"\"}\n    :host([${Attributes.USER_INACTIVE}]:not([${MediaUIAttributes.MEDIA_PAUSED}]):not([${MediaUIAttributes.MEDIA_IS_AIRPLAYING}]):not([${MediaUIAttributes.MEDIA_IS_CASTING}]):not([${Attributes.AUDIO}])) ::slotted(:not([slot=media]):not([slot=poster]):not([${Attributes.NO_AUTOHIDE}])) {\n      opacity: 0;\n      transition: opacity 1s;\n    }\n\n    :host([${Attributes.USER_INACTIVE}]:not([${MediaUIAttributes.MEDIA_PAUSED}]):not([${MediaUIAttributes.MEDIA_IS_CASTING}]):not([${Attributes.AUDIO}])) ::slotted([slot=media]) {\n      cursor: none;\n    }\n\n    ::slotted(media-control-bar)  {\n      align-self: stretch;\n    }\n\n    ${/* ::slotted([slot=poster]) doesn't work for slot fallback content so hide parent slot instead */\n\"\"}\n    :host(:not([${Attributes.AUDIO}])[${MediaUIAttributes.MEDIA_HAS_PLAYED}]) slot[name=poster] {\n      display: none;\n    }\n\n    ::slotted([role=\"menu\"]) {\n      align-self: end;\n    }\n\n    ::slotted([role=\"dialog\"]) {\n      align-self: center;\n    }\n  </style>\n\n  <slot name=\"media\" part=\"layer media-layer\"></slot>\n  <slot name=\"poster\" part=\"layer poster-layer\"></slot>\n  <slot name=\"gestures-chrome\" part=\"layer gesture-layer\">\n    <media-gesture-receiver slot=\"gestures-chrome\"></media-gesture-receiver>\n  </slot>\n  <span part=\"layer vertical-layer\">\n    <slot name=\"top-chrome\" part=\"top chrome\"></slot>\n    <slot name=\"middle-chrome\" part=\"middle chrome\"></slot>\n    <slot name=\"centered-chrome\" part=\"layer centered-layer center centered chrome\"></slot>\n    ${/* default, effectively \"bottom-chrome\" */\n\"\"}\n    <slot part=\"bottom chrome\"></slot>\n  </span>\n`;\nconst MEDIA_UI_ATTRIBUTE_NAMES = Object.values(MediaUIAttributes);\nconst defaultBreakpoints = \"sm:384 md:576 lg:768 xl:960\";\nfunction resizeCallback(entry) {\n  setBreakpoints(entry.target, entry.contentRect.width);\n}\nfunction setBreakpoints(container, width) {\n  var _a;\n  if (!container.isConnected)\n    return;\n  const breakpoints = (_a = container.getAttribute(Attributes.BREAKPOINTS)) != null ? _a : defaultBreakpoints;\n  const ranges = createBreakpointMap(breakpoints);\n  const activeBreakpoints = getBreakpoints(ranges, width);\n  let changed = false;\n  Object.keys(ranges).forEach((name) => {\n    if (activeBreakpoints.includes(name)) {\n      if (!container.hasAttribute(`breakpoint${name}`)) {\n        container.setAttribute(`breakpoint${name}`, \"\");\n        changed = true;\n      }\n      return;\n    }\n    if (container.hasAttribute(`breakpoint${name}`)) {\n      container.removeAttribute(`breakpoint${name}`);\n      changed = true;\n    }\n  });\n  if (changed) {\n    const evt = new CustomEvent(MediaStateChangeEvents.BREAKPOINTS_CHANGE, {\n      detail: activeBreakpoints\n    });\n    container.dispatchEvent(evt);\n  }\n}\nfunction createBreakpointMap(breakpoints) {\n  const pairs = breakpoints.split(/\\s+/);\n  return Object.fromEntries(pairs.map((pair) => pair.split(\":\")));\n}\nfunction getBreakpoints(breakpoints, width) {\n  return Object.keys(breakpoints).filter((name) => {\n    return width >= parseInt(breakpoints[name]);\n  });\n}\nclass MediaContainer extends globalThis.HTMLElement {\n  constructor() {\n    super();\n    __privateAdd(this, _handlePointerMove);\n    __privateAdd(this, _handlePointerUp);\n    __privateAdd(this, _setInactive);\n    __privateAdd(this, _setActive);\n    __privateAdd(this, _scheduleInactive);\n    __privateAdd(this, _pointerDownTimeStamp, 0);\n    __privateAdd(this, _currentMedia, null);\n    __privateAdd(this, _inactiveTimeout, null);\n    __privateAdd(this, _autohide, void 0);\n    this.breakpointsComputed = false;\n    if (!this.shadowRoot) {\n      this.attachShadow({ mode: \"open\" });\n      this.shadowRoot.appendChild(template.content.cloneNode(true));\n    }\n    const mutationCallback = (mutationsList) => {\n      const media = this.media;\n      for (const mutation of mutationsList) {\n        if (mutation.type === \"childList\") {\n          mutation.removedNodes.forEach((node) => {\n            if (node.slot == \"media\" && mutation.target == this) {\n              let previousSibling = mutation.previousSibling && mutation.previousSibling.previousElementSibling;\n              if (!previousSibling || !media) {\n                this.mediaUnsetCallback(node);\n              } else {\n                let wasFirst = previousSibling.slot !== \"media\";\n                while ((previousSibling = previousSibling.previousSibling) !== null) {\n                  if (previousSibling.slot == \"media\")\n                    wasFirst = false;\n                }\n                if (wasFirst)\n                  this.mediaUnsetCallback(node);\n              }\n            }\n          });\n          if (media) {\n            mutation.addedNodes.forEach((node) => {\n              if (node === media) {\n                this.handleMediaUpdated(media);\n              }\n            });\n          }\n        }\n      }\n    };\n    const mutationObserver = new MutationObserver(mutationCallback);\n    mutationObserver.observe(this, { childList: true, subtree: true });\n    let pendingResizeCb = false;\n    const deferResizeCallback = (entry) => {\n      if (pendingResizeCb)\n        return;\n      setTimeout(() => {\n        resizeCallback(entry);\n        pendingResizeCb = false;\n        if (!this.breakpointsComputed) {\n          this.breakpointsComputed = true;\n          this.dispatchEvent(\n            new CustomEvent(MediaStateChangeEvents.BREAKPOINTS_COMPUTED, {\n              bubbles: true,\n              composed: true\n            })\n          );\n        }\n      }, 0);\n      pendingResizeCb = true;\n    };\n    observeResize(this, deferResizeCallback);\n    const chainedSlot = this.querySelector(\n      \":scope > slot[slot=media]\"\n    );\n    if (chainedSlot) {\n      chainedSlot.addEventListener(\"slotchange\", () => {\n        const slotEls = chainedSlot.assignedElements({ flatten: true });\n        if (!slotEls.length) {\n          if (__privateGet(this, _currentMedia)) {\n            this.mediaUnsetCallback(__privateGet(this, _currentMedia));\n          }\n          return;\n        }\n        this.handleMediaUpdated(this.media);\n      });\n    }\n  }\n  static get observedAttributes() {\n    return [Attributes.AUTOHIDE, Attributes.GESTURES_DISABLED].concat(MEDIA_UI_ATTRIBUTE_NAMES).filter(\n      (name) => ![\n        MediaUIAttributes.MEDIA_RENDITION_LIST,\n        MediaUIAttributes.MEDIA_AUDIO_TRACK_LIST,\n        MediaUIAttributes.MEDIA_CHAPTERS_CUES,\n        MediaUIAttributes.MEDIA_WIDTH,\n        MediaUIAttributes.MEDIA_HEIGHT\n      ].includes(name)\n    );\n  }\n  // Could share this code with media-chrome-html-element instead\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    if (attrName.toLowerCase() == Attributes.AUTOHIDE) {\n      this.autohide = newValue;\n    }\n  }\n  // First direct child with slot=media, or null\n  /**\n   * @returns {HTMLVideoElement &\n   * {buffered,\n   * webkitEnterFullscreen?,\n   * webkitExitFullscreen?,\n   * requestCast?,\n   * webkitShowPlaybackTargetPicker?,\n   * videoTracks?,\n   * }}\n   */\n  get media() {\n    let media = this.querySelector(\":scope > [slot=media]\");\n    if ((media == null ? void 0 : media.nodeName) == \"SLOT\")\n      media = media.assignedElements({ flatten: true })[0];\n    return media;\n  }\n  /**\n   * @param {HTMLMediaElement} media\n   */\n  async handleMediaUpdated(media) {\n    if (!media)\n      return;\n    __privateSet(this, _currentMedia, media);\n    if (media.localName.includes(\"-\")) {\n      await globalThis.customElements.whenDefined(media.localName);\n    }\n    this.mediaSetCallback(media);\n  }\n  connectedCallback() {\n    var _a;\n    const isAudioChrome = this.getAttribute(Attributes.AUDIO) != null;\n    const label = isAudioChrome ? nouns.AUDIO_PLAYER() : nouns.VIDEO_PLAYER();\n    this.setAttribute(\"role\", \"region\");\n    this.setAttribute(\"aria-label\", label);\n    this.handleMediaUpdated(this.media);\n    this.setAttribute(Attributes.USER_INACTIVE, \"\");\n    this.addEventListener(\"pointerdown\", this);\n    this.addEventListener(\"pointermove\", this);\n    this.addEventListener(\"pointerup\", this);\n    this.addEventListener(\"mouseleave\", this);\n    this.addEventListener(\"keyup\", this);\n    (_a = globalThis.window) == null ? void 0 : _a.addEventListener(\"mouseup\", this);\n  }\n  disconnectedCallback() {\n    var _a;\n    if (this.media) {\n      this.mediaUnsetCallback(this.media);\n    }\n    (_a = globalThis.window) == null ? void 0 : _a.removeEventListener(\"mouseup\", this);\n  }\n  /**\n   * @abstract\n   * @param {HTMLMediaElement} media\n   */\n  mediaSetCallback(media) {\n  }\n  // eslint-disable-line\n  /**\n   * @param {HTMLMediaElement} media\n   */\n  mediaUnsetCallback(media) {\n    __privateSet(this, _currentMedia, null);\n  }\n  handleEvent(event) {\n    switch (event.type) {\n      case \"pointerdown\":\n        __privateSet(this, _pointerDownTimeStamp, event.timeStamp);\n        break;\n      case \"pointermove\":\n        __privateMethod(this, _handlePointerMove, handlePointerMove_fn).call(this, event);\n        break;\n      case \"pointerup\":\n        __privateMethod(this, _handlePointerUp, handlePointerUp_fn).call(this, event);\n        break;\n      case \"mouseleave\":\n        __privateMethod(this, _setInactive, setInactive_fn).call(this);\n        break;\n      case \"mouseup\":\n        this.removeAttribute(Attributes.KEYBOARD_CONTROL);\n        break;\n      case \"keyup\":\n        __privateMethod(this, _scheduleInactive, scheduleInactive_fn).call(this);\n        this.setAttribute(Attributes.KEYBOARD_CONTROL, \"\");\n        break;\n    }\n  }\n  set autohide(seconds) {\n    const parsedSeconds = Number(seconds);\n    __privateSet(this, _autohide, isNaN(parsedSeconds) ? 0 : parsedSeconds);\n  }\n  get autohide() {\n    return (__privateGet(this, _autohide) === void 0 ? 2 : __privateGet(this, _autohide)).toString();\n  }\n}\n_pointerDownTimeStamp = new WeakMap();\n_currentMedia = new WeakMap();\n_inactiveTimeout = new WeakMap();\n_autohide = new WeakMap();\n_handlePointerMove = new WeakSet();\nhandlePointerMove_fn = function(event) {\n  if (event.pointerType !== \"mouse\") {\n    const MAX_TAP_DURATION = 250;\n    if (event.timeStamp - __privateGet(this, _pointerDownTimeStamp) < MAX_TAP_DURATION)\n      return;\n  }\n  __privateMethod(this, _setActive, setActive_fn).call(this);\n  clearTimeout(__privateGet(this, _inactiveTimeout));\n  if ([this, this.media].includes(event.target)) {\n    __privateMethod(this, _scheduleInactive, scheduleInactive_fn).call(this);\n  }\n};\n_handlePointerUp = new WeakSet();\nhandlePointerUp_fn = function(event) {\n  if (event.pointerType === \"touch\") {\n    const controlsVisible = !this.hasAttribute(Attributes.USER_INACTIVE);\n    if ([this, this.media].includes(event.target) && controlsVisible) {\n      __privateMethod(this, _setInactive, setInactive_fn).call(this);\n    } else {\n      __privateMethod(this, _scheduleInactive, scheduleInactive_fn).call(this);\n    }\n  } else if (event.composedPath().some(\n    (el) => [\"media-play-button\", \"media-fullscreen-button\"].includes(\n      el == null ? void 0 : el.localName\n    )\n  )) {\n    __privateMethod(this, _scheduleInactive, scheduleInactive_fn).call(this);\n  }\n};\n_setInactive = new WeakSet();\nsetInactive_fn = function() {\n  if (__privateGet(this, _autohide) < 0)\n    return;\n  if (this.hasAttribute(Attributes.USER_INACTIVE))\n    return;\n  this.setAttribute(Attributes.USER_INACTIVE, \"\");\n  const evt = new globalThis.CustomEvent(\n    MediaStateChangeEvents.USER_INACTIVE,\n    { composed: true, bubbles: true, detail: true }\n  );\n  this.dispatchEvent(evt);\n};\n_setActive = new WeakSet();\nsetActive_fn = function() {\n  if (!this.hasAttribute(Attributes.USER_INACTIVE))\n    return;\n  this.removeAttribute(Attributes.USER_INACTIVE);\n  const evt = new globalThis.CustomEvent(\n    MediaStateChangeEvents.USER_INACTIVE,\n    { composed: true, bubbles: true, detail: false }\n  );\n  this.dispatchEvent(evt);\n};\n_scheduleInactive = new WeakSet();\nscheduleInactive_fn = function() {\n  __privateMethod(this, _setActive, setActive_fn).call(this);\n  clearTimeout(__privateGet(this, _inactiveTimeout));\n  const autohide = parseInt(this.autohide);\n  if (autohide < 0)\n    return;\n  __privateSet(this, _inactiveTimeout, setTimeout(() => {\n    __privateMethod(this, _setInactive, setInactive_fn).call(this);\n  }, autohide * 1e3));\n};\nif (!globalThis.customElements.get(\"media-container\")) {\n  globalThis.customElements.define(\"media-container\", MediaContainer);\n}\nvar media_container_default = MediaContainer;\nexport {\n  Attributes,\n  MediaContainer,\n  media_container_default as default\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar __privateSet = (obj, member, value, setter) => {\n  __accessCheck(obj, member, \"write to private field\");\n  setter ? setter.call(obj, value) : member.set(obj, value);\n  return value;\n};\nvar _el, _attr, _defaultSet, _tokenSet, _tokens, tokens_get;\nclass AttributeTokenList {\n  constructor(el, attr, { defaultValue } = { defaultValue: void 0 }) {\n    __privateAdd(this, _tokens);\n    __privateAdd(this, _el, void 0);\n    __privateAdd(this, _attr, void 0);\n    __privateAdd(this, _defaultSet, void 0);\n    __privateAdd(this, _tokenSet, /* @__PURE__ */ new Set());\n    __privateSet(this, _el, el);\n    __privateSet(this, _attr, attr);\n    __privateSet(this, _defaultSet, new Set(defaultValue));\n  }\n  [Symbol.iterator]() {\n    return __privateGet(this, _tokens, tokens_get).values();\n  }\n  get length() {\n    return __privateGet(this, _tokens, tokens_get).size;\n  }\n  get value() {\n    var _a;\n    return (_a = [...__privateGet(this, _tokens, tokens_get)].join(\" \")) != null ? _a : \"\";\n  }\n  set value(val) {\n    var _a;\n    if (val === this.value)\n      return;\n    __privateSet(this, _tokenSet, /* @__PURE__ */ new Set());\n    this.add(...(_a = val == null ? void 0 : val.split(\" \")) != null ? _a : []);\n  }\n  toString() {\n    return this.value;\n  }\n  item(index) {\n    return [...__privateGet(this, _tokens, tokens_get)][index];\n  }\n  values() {\n    return __privateGet(this, _tokens, tokens_get).values();\n  }\n  forEach(callback, thisArg) {\n    __privateGet(this, _tokens, tokens_get).forEach(callback, thisArg);\n  }\n  add(...tokens) {\n    var _a, _b;\n    tokens.forEach((t) => __privateGet(this, _tokenSet).add(t));\n    if (this.value === \"\" && !((_a = __privateGet(this, _el)) == null ? void 0 : _a.hasAttribute(`${__privateGet(this, _attr)}`))) {\n      return;\n    }\n    (_b = __privateGet(this, _el)) == null ? void 0 : _b.setAttribute(`${__privateGet(this, _attr)}`, `${this.value}`);\n  }\n  remove(...tokens) {\n    var _a;\n    tokens.forEach((t) => __privateGet(this, _tokenSet).delete(t));\n    (_a = __privateGet(this, _el)) == null ? void 0 : _a.setAttribute(`${__privateGet(this, _attr)}`, `${this.value}`);\n  }\n  contains(token) {\n    return __privateGet(this, _tokens, tokens_get).has(token);\n  }\n  toggle(token, force) {\n    if (typeof force !== \"undefined\") {\n      if (force) {\n        this.add(token);\n        return true;\n      } else {\n        this.remove(token);\n        return false;\n      }\n    }\n    if (this.contains(token)) {\n      this.remove(token);\n      return false;\n    }\n    this.add(token);\n    return true;\n  }\n  replace(oldToken, newToken) {\n    this.remove(oldToken);\n    this.add(newToken);\n    return oldToken === newToken;\n  }\n}\n_el = new WeakMap();\n_attr = new WeakMap();\n_defaultSet = new WeakMap();\n_tokenSet = new WeakMap();\n_tokens = new WeakSet();\ntokens_get = function() {\n  return __privateGet(this, _tokenSet).size ? __privateGet(this, _tokenSet) : __privateGet(this, _defaultSet);\n};\nexport {\n  AttributeTokenList\n};\n", "import { MediaUIAttributes, TextTrackKinds } from \"../constants.js\";\nconst splitTextTracksStr = (textTracksStr = \"\") => textTracksStr.split(/\\s+/);\nconst parseTextTrackStr = (textTrackStr = \"\") => {\n  const [kind, language, encodedLabel] = textTrackStr.split(\":\");\n  const label = encodedLabel ? decodeURIComponent(encodedLabel) : void 0;\n  return {\n    kind: kind === \"cc\" ? TextTrackKinds.CAPTIONS : TextTrackKinds.SUBTITLES,\n    language,\n    label\n  };\n};\nconst parseTextTracksStr = (textTracksStr = \"\", textTrackLikeObj = {}) => {\n  return splitTextTracksStr(textTracksStr).map((textTrackStr) => {\n    const textTrackObj = parseTextTrackStr(textTrackStr);\n    return {\n      ...textTrackLikeObj,\n      ...textTrackObj\n    };\n  });\n};\nconst parseTracks = (trackOrTracks) => {\n  if (!trackOrTracks)\n    return [];\n  if (Array.isArray(trackOrTracks)) {\n    return trackOrTracks.map((trackObjOrStr) => {\n      if (typeof trackObjOrStr === \"string\") {\n        return parseTextTrackStr(trackObjOrStr);\n      }\n      return trackObjOrStr;\n    });\n  }\n  if (typeof trackOrTracks === \"string\") {\n    return parseTextTracksStr(trackOrTracks);\n  }\n  return [trackOrTracks];\n};\nconst formatTextTrackObj = ({ kind, label, language } = { kind: \"subtitles\" }) => {\n  if (!label)\n    return language;\n  return `${kind === \"captions\" ? \"cc\" : \"sb\"}:${language}:${encodeURIComponent(\n    label\n  )}`;\n};\nconst stringifyTextTrackList = (textTracks = []) => {\n  return Array.prototype.map.call(textTracks, formatTextTrackObj).join(\" \");\n};\nconst isMatchingPropOf = (key, value) => (obj) => obj[key] === value;\nconst textTrackObjAsPred = (filterObj) => {\n  const preds = Object.entries(filterObj).map(([key, value]) => {\n    return isMatchingPropOf(key, value);\n  });\n  return (textTrack) => preds.every((pred) => pred(textTrack));\n};\nconst updateTracksModeTo = (mode, tracks = [], tracksToUpdate = []) => {\n  const preds = parseTracks(tracksToUpdate).map(textTrackObjAsPred);\n  const isTrackToUpdate = (textTrack) => {\n    return preds.some((pred) => pred(textTrack));\n  };\n  Array.from(tracks).filter(isTrackToUpdate).forEach((textTrack) => {\n    textTrack.mode = mode;\n  });\n};\nconst getTextTracksList = (media, filterPredOrObj = () => true) => {\n  if (!(media == null ? void 0 : media.textTracks))\n    return [];\n  const filterPred = typeof filterPredOrObj === \"function\" ? filterPredOrObj : textTrackObjAsPred(filterPredOrObj);\n  return Array.from(media.textTracks).filter(filterPred);\n};\nconst areSubsOn = (el) => {\n  var _a;\n  const showingSubtitles = !!((_a = el.mediaSubtitlesShowing) == null ? void 0 : _a.length) || el.hasAttribute(MediaUIAttributes.MEDIA_SUBTITLES_SHOWING);\n  return showingSubtitles;\n};\nexport {\n  areSubsOn,\n  formatTextTrackObj,\n  getTextTracksList,\n  isMatchingPropOf,\n  parseTextTrackStr,\n  parseTextTracksStr,\n  parseTracks,\n  splitTextTracksStr,\n  stringifyTextTrackList,\n  textTrackObjAsPred,\n  updateTracksModeTo\n};\n", "import { WebkitPresentationModes } from \"../constants.js\";\nimport { containsComposedNode } from \"./element-utils.js\";\nimport { document } from \"./server-safe-globals.js\";\nconst enterFullscreen = (stateOwners) => {\n  var _a;\n  const { media, fullscreenElement } = stateOwners;\n  const enterFullscreenKey = fullscreenElement && \"requestFullscreen\" in fullscreenElement ? \"requestFullscreen\" : fullscreenElement && \"webkitRequestFullScreen\" in fullscreenElement ? \"webkitRequestFullScreen\" : void 0;\n  if (enterFullscreenKey) {\n    const maybePromise = (_a = fullscreenElement[enterFullscreenKey]) == null ? void 0 : _a.call(fullscreenElement);\n    if (maybePromise instanceof Promise) {\n      return maybePromise.catch(() => {\n      });\n    }\n  } else if (media == null ? void 0 : media.webkitEnterFullscreen) {\n    media.webkitEnterFullscreen();\n  } else if (media == null ? void 0 : media.requestFullscreen) {\n    media.requestFullscreen();\n  }\n};\nconst exitFullscreenKey = \"exitFullscreen\" in document ? \"exitFullscreen\" : \"webkitExitFullscreen\" in document ? \"webkitExitFullscreen\" : \"webkitCancelFullScreen\" in document ? \"webkitCancelFullScreen\" : void 0;\nconst exitFullscreen = (stateOwners) => {\n  var _a;\n  const { documentElement } = stateOwners;\n  if (exitFullscreenKey) {\n    const maybePromise = (_a = documentElement == null ? void 0 : documentElement[exitFullscreenKey]) == null ? void 0 : _a.call(documentElement);\n    if (maybePromise instanceof Promise) {\n      return maybePromise.catch(() => {\n      });\n    }\n  }\n};\nconst fullscreenElementKey = \"fullscreenElement\" in document ? \"fullscreenElement\" : \"webkitFullscreenElement\" in document ? \"webkitFullscreenElement\" : void 0;\nconst getFullscreenElement = (stateOwners) => {\n  const { documentElement, media } = stateOwners;\n  const docFullscreenElement = documentElement == null ? void 0 : documentElement[fullscreenElementKey];\n  if (!docFullscreenElement && \"webkitDisplayingFullscreen\" in media && \"webkitPresentationMode\" in media && media.webkitDisplayingFullscreen && media.webkitPresentationMode === WebkitPresentationModes.FULLSCREEN) {\n    return media;\n  }\n  return docFullscreenElement;\n};\nconst isFullscreen = (stateOwners) => {\n  var _a;\n  const { media, documentElement, fullscreenElement = media } = stateOwners;\n  if (!media || !documentElement)\n    return false;\n  const currentFullscreenElement = getFullscreenElement(stateOwners);\n  if (!currentFullscreenElement)\n    return false;\n  if (currentFullscreenElement === fullscreenElement || currentFullscreenElement === media) {\n    return true;\n  }\n  if (currentFullscreenElement.localName.includes(\"-\")) {\n    let currentRoot = currentFullscreenElement.shadowRoot;\n    if (!(fullscreenElementKey in currentRoot)) {\n      return containsComposedNode(\n        currentFullscreenElement,\n        /** @TODO clean up type assumptions (e.g. Node) (CJP) */\n        // @ts-ignore\n        fullscreenElement\n      );\n    }\n    while (currentRoot == null ? void 0 : currentRoot[fullscreenElementKey]) {\n      if (currentRoot[fullscreenElementKey] === fullscreenElement)\n        return true;\n      currentRoot = (_a = currentRoot[fullscreenElementKey]) == null ? void 0 : _a.shadowRoot;\n    }\n  }\n  return false;\n};\nconst fullscreenEnabledKey = \"fullscreenEnabled\" in document ? \"fullscreenEnabled\" : \"webkitFullscreenEnabled\" in document ? \"webkitFullscreenEnabled\" : void 0;\nconst isFullscreenEnabled = (stateOwners) => {\n  const { documentElement, media } = stateOwners;\n  return !!(documentElement == null ? void 0 : documentElement[fullscreenEnabledKey]) || media && \"webkitSupportsFullscreen\" in media;\n};\nexport {\n  enterFullscreen,\n  exitFullscreen,\n  getFullscreenElement,\n  isFullscreen,\n  isFullscreenEnabled\n};\n", "import { globalThis, document } from \"./server-safe-globals.js\";\nimport { delay } from \"./utils.js\";\nimport { isFullscreenEnabled } from \"./fullscreen-api.js\";\nlet testMediaEl;\nconst getTestMediaEl = () => {\n  var _a, _b;\n  if (testMediaEl)\n    return testMediaEl;\n  testMediaEl = (_b = (_a = document) == null ? void 0 : _a.createElement) == null ? void 0 : _b.call(_a, \"video\");\n  return testMediaEl;\n};\nconst hasVolumeSupportAsync = async (mediaEl = getTestMediaEl()) => {\n  if (!mediaEl)\n    return false;\n  const prevVolume = mediaEl.volume;\n  mediaEl.volume = prevVolume / 2 + 0.1;\n  const abortController = new AbortController();\n  const volumeSupported = await Promise.race([\n    dispatchedVolumeChange(mediaEl, abortController.signal),\n    volumeChanged(mediaEl, prevVolume)\n  ]);\n  abortController.abort();\n  return volumeSupported;\n};\nconst dispatchedVolumeChange = (mediaEl, signal) => {\n  return new Promise((resolve) => {\n    mediaEl.addEventListener(\"volumechange\", () => resolve(true), { signal });\n  });\n};\nconst volumeChanged = async (mediaEl, prevVolume) => {\n  for (let i = 0; i < 10; i++) {\n    if (mediaEl.volume === prevVolume)\n      return false;\n    await delay(10);\n  }\n  return mediaEl.volume !== prevVolume;\n};\nconst isSafari = /.*Version\\/.*Safari\\/.*/.test(\n  globalThis.navigator.userAgent\n);\nconst hasPipSupport = (mediaEl = getTestMediaEl()) => {\n  if (globalThis.matchMedia(\"(display-mode: standalone)\").matches && isSafari)\n    return false;\n  return typeof (mediaEl == null ? void 0 : mediaEl.requestPictureInPicture) === \"function\";\n};\nconst hasFullscreenSupport = (mediaEl = getTestMediaEl()) => {\n  return isFullscreenEnabled({ documentElement: document, media: mediaEl });\n};\nconst fullscreenSupported = hasFullscreenSupport();\nconst pipSupported = hasPipSupport();\nconst airplaySupported = !!globalThis.WebKitPlaybackTargetAvailabilityEvent;\nconst castSupported = !!globalThis.chrome;\nexport {\n  airplaySupported,\n  castSupported,\n  fullscreenSupported,\n  getTestMediaEl,\n  hasFullscreenSupport,\n  hasPipSupport,\n  hasVolumeSupportAsync,\n  pipSupported\n};\n", "import { TextTrackKinds, TextTrackModes } from \"../constants.js\";\nimport { getTextTracksList, updateTracksModeTo } from \"../utils/captions.js\";\nconst getSubtitleTracks = (stateOwners) => {\n  return getTextTracksList(stateOwners.media, (textTrack) => {\n    return [TextTrackKinds.SUBTITLES, TextTrackKinds.CAPTIONS].includes(\n      textTrack.kind\n    );\n  }).sort((a, b) => a.kind >= b.kind ? 1 : -1);\n};\nconst getShowingSubtitleTracks = (stateOwners) => {\n  return getTextTracksList(stateOwners.media, (textTrack) => {\n    return textTrack.mode === TextTrackModes.SHOWING && [TextTrackKinds.SUBTITLES, TextTrackKinds.CAPTIONS].includes(\n      textTrack.kind\n    );\n  });\n};\nconst toggleSubtitleTracks = (stateOwners, force) => {\n  const tracks = getSubtitleTracks(stateOwners);\n  const showingSubitleTracks = getShowingSubtitleTracks(stateOwners);\n  const subtitlesShowing = !!showingSubitleTracks.length;\n  if (!tracks.length)\n    return;\n  if (force === false || subtitlesShowing && force !== true) {\n    updateTracksModeTo(TextTrackModes.DISABLED, tracks, showingSubitleTracks);\n  } else if (force === true || !subtitlesShowing && force !== false) {\n    let subTrack = tracks[0];\n    const { options } = stateOwners;\n    if (!(options == null ? void 0 : options.noSubtitlesLangPref)) {\n      const subtitlesPref = globalThis.localStorage.getItem(\n        \"media-chrome-pref-subtitles-lang\"\n      );\n      const userLangPrefs = subtitlesPref ? [subtitlesPref, ...globalThis.navigator.languages] : globalThis.navigator.languages;\n      const preferredAvailableSubs = tracks.filter((textTrack) => {\n        return userLangPrefs.some(\n          (lang) => textTrack.language.toLowerCase().startsWith(lang.split(\"-\")[0])\n        );\n      }).sort((textTrackA, textTrackB) => {\n        const idxA = userLangPrefs.findIndex(\n          (lang) => textTrackA.language.toLowerCase().startsWith(lang.split(\"-\")[0])\n        );\n        const idxB = userLangPrefs.findIndex(\n          (lang) => textTrackB.language.toLowerCase().startsWith(lang.split(\"-\")[0])\n        );\n        return idxA - idxB;\n      });\n      if (preferredAvailableSubs[0]) {\n        subTrack = preferredAvailableSubs[0];\n      }\n    }\n    const { language, label, kind } = subTrack;\n    updateTracksModeTo(TextTrackModes.DISABLED, tracks, showingSubitleTracks);\n    updateTracksModeTo(TextTrackModes.SHOWING, tracks, [\n      { language, label, kind }\n    ]);\n  }\n};\nconst areValuesEq = (x, y) => {\n  if (x === y)\n    return true;\n  if (typeof x !== typeof y)\n    return false;\n  if (typeof x === \"number\" && Number.isNaN(x) && Number.isNaN(y))\n    return true;\n  if (typeof x !== \"object\")\n    return false;\n  if (Array.isArray(x))\n    return areArraysEq(x, y);\n  return Object.entries(x).every(\n    // NOTE: Checking key in y to disambiguate between between missing keys and keys whose value are undefined (CJP)\n    ([key, value]) => key in y && areValuesEq(value, y[key])\n  );\n};\nconst areArraysEq = (xs, ys) => {\n  const xIsArray = Array.isArray(xs);\n  const yIsArray = Array.isArray(ys);\n  if (xIsArray !== yIsArray)\n    return false;\n  if (!(xIsArray || yIsArray))\n    return true;\n  if (xs.length !== ys.length)\n    return false;\n  return xs.every((x, i) => areValuesEq(x, ys[i]));\n};\nexport {\n  areArraysEq,\n  areValuesEq,\n  getShowingSubtitleTracks,\n  getSubtitleTracks,\n  toggleSubtitleTracks\n};\n", "import { document, globalThis } from \"../utils/server-safe-globals.js\";\nimport {\n  AvailabilityStates,\n  StreamTypes,\n  TextTrackKinds\n} from \"../constants.js\";\nimport { containsComposedNode } from \"../utils/element-utils.js\";\nimport { enterFullscreen, exitFullscreen, isFullscreen } from \"../utils/fullscreen-api.js\";\nimport {\n  airplaySupported,\n  castSupported,\n  fullscreenSupported,\n  hasFullscreenSupport,\n  hasPipSupport,\n  hasVolumeSupportAsync,\n  pipSupported\n} from \"../utils/platform-tests.js\";\nimport {\n  getShowingSubtitleTracks,\n  getSubtitleTracks,\n  toggleSubtitleTracks\n} from \"./util.js\";\nimport { getTextTracksList } from \"../utils/captions.js\";\nimport { isValidNumber } from \"../utils/utils.js\";\nconst StreamTypeValues = Object.values(StreamTypes);\nlet volumeSupported;\nconst volumeSupportPromise = hasVolumeSupportAsync().then((supported) => {\n  volumeSupported = supported;\n  return volumeSupported;\n});\nconst prepareStateOwners = async (...stateOwners) => {\n  await Promise.all(\n    stateOwners.filter((x) => x).map(async (stateOwner) => {\n      if (!(\"localName\" in stateOwner && stateOwner instanceof globalThis.HTMLElement)) {\n        return;\n      }\n      const name = stateOwner.localName;\n      if (!name.includes(\"-\"))\n        return;\n      const classDef = globalThis.customElements.get(name);\n      if (classDef && stateOwner instanceof classDef)\n        return;\n      await globalThis.customElements.whenDefined(name);\n      globalThis.customElements.upgrade(stateOwner);\n    })\n  );\n};\nconst stateMediator = {\n  mediaWidth: {\n    get(stateOwners) {\n      var _a;\n      const { media } = stateOwners;\n      return (_a = media == null ? void 0 : media.videoWidth) != null ? _a : 0;\n    },\n    mediaEvents: [\"resize\"]\n  },\n  mediaHeight: {\n    get(stateOwners) {\n      var _a;\n      const { media } = stateOwners;\n      return (_a = media == null ? void 0 : media.videoHeight) != null ? _a : 0;\n    },\n    mediaEvents: [\"resize\"]\n  },\n  mediaPaused: {\n    get(stateOwners) {\n      var _a;\n      const { media } = stateOwners;\n      return (_a = media == null ? void 0 : media.paused) != null ? _a : true;\n    },\n    set(value, stateOwners) {\n      var _a;\n      const { media } = stateOwners;\n      if (!media)\n        return;\n      if (value) {\n        media.pause();\n      } else {\n        (_a = media.play()) == null ? void 0 : _a.catch(() => {\n        });\n      }\n    },\n    mediaEvents: [\"play\", \"playing\", \"pause\", \"emptied\"]\n  },\n  mediaHasPlayed: {\n    // We want to let the user know that the media started playing at any point (`media-has-played`).\n    // Since these propagators are all called when boostrapping state, let's verify this is\n    // a real playing event by checking that 1) there's media and 2) it isn't currently paused.\n    get(stateOwners, event) {\n      const { media } = stateOwners;\n      if (!media)\n        return false;\n      if (!event)\n        return !media.paused;\n      return event.type === \"playing\";\n    },\n    mediaEvents: [\"playing\", \"emptied\"]\n  },\n  mediaEnded: {\n    get(stateOwners) {\n      var _a;\n      const { media } = stateOwners;\n      return (_a = media == null ? void 0 : media.ended) != null ? _a : false;\n    },\n    mediaEvents: [\"seeked\", \"ended\", \"emptied\"]\n  },\n  mediaPlaybackRate: {\n    get(stateOwners) {\n      var _a;\n      const { media } = stateOwners;\n      return (_a = media == null ? void 0 : media.playbackRate) != null ? _a : 1;\n    },\n    set(value, stateOwners) {\n      const { media } = stateOwners;\n      if (!media)\n        return;\n      if (!Number.isFinite(+value))\n        return;\n      media.playbackRate = +value;\n    },\n    mediaEvents: [\"ratechange\", \"loadstart\"]\n  },\n  mediaMuted: {\n    get(stateOwners) {\n      var _a;\n      const { media } = stateOwners;\n      return (_a = media == null ? void 0 : media.muted) != null ? _a : false;\n    },\n    set(value, stateOwners) {\n      const { media } = stateOwners;\n      if (!media)\n        return;\n      media.muted = value;\n    },\n    mediaEvents: [\"volumechange\"]\n  },\n  mediaVolume: {\n    get(stateOwners) {\n      var _a;\n      const { media } = stateOwners;\n      return (_a = media == null ? void 0 : media.volume) != null ? _a : 1;\n    },\n    set(value, stateOwners) {\n      const { media } = stateOwners;\n      if (!media)\n        return;\n      try {\n        if (value == null) {\n          globalThis.localStorage.removeItem(\"media-chrome-pref-volume\");\n        } else {\n          globalThis.localStorage.setItem(\n            \"media-chrome-pref-volume\",\n            value.toString()\n          );\n        }\n      } catch (err) {\n      }\n      if (!Number.isFinite(+value))\n        return;\n      media.volume = +value;\n    },\n    mediaEvents: [\"volumechange\"],\n    stateOwnersUpdateHandlers: [\n      (handler, stateOwners) => {\n        const {\n          options: { noVolumePref }\n        } = stateOwners;\n        if (noVolumePref)\n          return;\n        try {\n          const volumePref = globalThis.localStorage.getItem(\n            \"media-chrome-pref-volume\"\n          );\n          if (volumePref == null)\n            return;\n          stateMediator.mediaVolume.set(+volumePref, stateOwners);\n          handler(+volumePref);\n        } catch (e) {\n          console.debug(\"Error getting volume pref\", e);\n        }\n      }\n    ]\n  },\n  // NOTE: Keeping this roughly equivalent to prior impl to reduce number of changes,\n  // however we may want to model \"derived\" state differently from \"primary\" state\n  // (in this case, derived === mediaVolumeLevel, primary === mediaMuted, mediaVolume) (CJP)\n  mediaVolumeLevel: {\n    get(stateOwners) {\n      const { media } = stateOwners;\n      if (typeof (media == null ? void 0 : media.volume) == \"undefined\")\n        return \"high\";\n      if (media.muted || media.volume === 0)\n        return \"off\";\n      if (media.volume < 0.5)\n        return \"low\";\n      if (media.volume < 0.75)\n        return \"medium\";\n      return \"high\";\n    },\n    mediaEvents: [\"volumechange\"]\n  },\n  mediaCurrentTime: {\n    get(stateOwners) {\n      var _a;\n      const { media } = stateOwners;\n      return (_a = media == null ? void 0 : media.currentTime) != null ? _a : 0;\n    },\n    set(value, stateOwners) {\n      const { media } = stateOwners;\n      if (!media || !isValidNumber(value))\n        return;\n      media.currentTime = value;\n    },\n    mediaEvents: [\"timeupdate\", \"loadedmetadata\"]\n  },\n  mediaDuration: {\n    get(stateOwners) {\n      const { media, options: { defaultDuration } = {} } = stateOwners;\n      if (defaultDuration && (!media || !media.duration || Number.isNaN(media.duration) || !Number.isFinite(media.duration))) {\n        return defaultDuration;\n      }\n      return Number.isFinite(media == null ? void 0 : media.duration) ? media.duration : Number.NaN;\n    },\n    mediaEvents: [\"durationchange\", \"loadedmetadata\", \"emptied\"]\n  },\n  mediaLoading: {\n    get(stateOwners) {\n      const { media } = stateOwners;\n      return (media == null ? void 0 : media.readyState) < 3;\n    },\n    mediaEvents: [\"waiting\", \"playing\", \"emptied\"]\n  },\n  mediaSeekable: {\n    get(stateOwners) {\n      var _a;\n      const { media } = stateOwners;\n      if (!((_a = media == null ? void 0 : media.seekable) == null ? void 0 : _a.length))\n        return void 0;\n      const start = media.seekable.start(0);\n      const end = media.seekable.end(media.seekable.length - 1);\n      if (!start && !end)\n        return void 0;\n      return [Number(start.toFixed(3)), Number(end.toFixed(3))];\n    },\n    mediaEvents: [\"loadedmetadata\", \"emptied\", \"progress\", \"seekablechange\"]\n  },\n  mediaBuffered: {\n    get(stateOwners) {\n      var _a;\n      const { media } = stateOwners;\n      const timeRanges = (_a = media == null ? void 0 : media.buffered) != null ? _a : [];\n      return Array.from(timeRanges).map((_, i) => [\n        Number(timeRanges.start(i).toFixed(3)),\n        Number(timeRanges.end(i).toFixed(3))\n      ]);\n    },\n    mediaEvents: [\"progress\", \"emptied\"]\n  },\n  mediaStreamType: {\n    get(stateOwners) {\n      const { media, options: { defaultStreamType } = {} } = stateOwners;\n      const usedDefaultStreamType = [\n        StreamTypes.LIVE,\n        StreamTypes.ON_DEMAND\n      ].includes(defaultStreamType) ? defaultStreamType : void 0;\n      if (!media)\n        return usedDefaultStreamType;\n      const { streamType } = media;\n      if (StreamTypeValues.includes(streamType)) {\n        if (streamType === StreamTypes.UNKNOWN) {\n          return usedDefaultStreamType;\n        }\n        return streamType;\n      }\n      const duration = media.duration;\n      if (duration === Infinity) {\n        return StreamTypes.LIVE;\n      } else if (Number.isFinite(duration)) {\n        return StreamTypes.ON_DEMAND;\n      }\n      return usedDefaultStreamType;\n    },\n    mediaEvents: [\n      \"emptied\",\n      \"durationchange\",\n      \"loadedmetadata\",\n      \"streamtypechange\"\n    ]\n  },\n  mediaTargetLiveWindow: {\n    get(stateOwners) {\n      const { media } = stateOwners;\n      if (!media)\n        return Number.NaN;\n      const { targetLiveWindow } = media;\n      const streamType = stateMediator.mediaStreamType.get(stateOwners);\n      if ((targetLiveWindow == null || Number.isNaN(targetLiveWindow)) && streamType === StreamTypes.LIVE) {\n        return 0;\n      }\n      return targetLiveWindow;\n    },\n    mediaEvents: [\n      \"emptied\",\n      \"durationchange\",\n      \"loadedmetadata\",\n      \"streamtypechange\",\n      \"targetlivewindowchange\"\n    ]\n  },\n  mediaTimeIsLive: {\n    get(stateOwners) {\n      const {\n        media,\n        // Default to 10 seconds\n        options: { liveEdgeOffset = 10 } = {}\n      } = stateOwners;\n      if (!media)\n        return false;\n      if (typeof media.liveEdgeStart === \"number\") {\n        if (Number.isNaN(media.liveEdgeStart))\n          return false;\n        return media.currentTime >= media.liveEdgeStart;\n      }\n      const live = stateMediator.mediaStreamType.get(stateOwners) === StreamTypes.LIVE;\n      if (!live)\n        return false;\n      const seekable = media.seekable;\n      if (!seekable)\n        return true;\n      if (!seekable.length)\n        return false;\n      const liveEdgeStart = seekable.end(seekable.length - 1) - liveEdgeOffset;\n      return media.currentTime >= liveEdgeStart;\n    },\n    mediaEvents: [\"playing\", \"timeupdate\", \"progress\", \"waiting\", \"emptied\"]\n  },\n  // Text Tracks modeling\n  mediaSubtitlesList: {\n    get(stateOwners) {\n      return getSubtitleTracks(stateOwners).map(\n        ({ kind, label, language }) => ({ kind, label, language })\n      );\n    },\n    mediaEvents: [\"loadstart\"],\n    textTracksEvents: [\"addtrack\", \"removetrack\"]\n  },\n  mediaSubtitlesShowing: {\n    get(stateOwners) {\n      return getShowingSubtitleTracks(stateOwners).map(\n        ({ kind, label, language }) => ({ kind, label, language })\n      );\n    },\n    mediaEvents: [\"loadstart\"],\n    textTracksEvents: [\"addtrack\", \"removetrack\", \"change\"],\n    stateOwnersUpdateHandlers: [\n      (_handler, stateOwners) => {\n        var _a, _b;\n        const { media, options } = stateOwners;\n        if (!media)\n          return;\n        const updateDefaultSubtitlesCallback = (event) => {\n          var _a2;\n          if (!options.defaultSubtitles)\n            return;\n          const nonSubsEvent = event && ![TextTrackKinds.CAPTIONS, TextTrackKinds.SUBTITLES].includes(\n            // @ts-ignore\n            (_a2 = event == null ? void 0 : event.track) == null ? void 0 : _a2.kind\n          );\n          if (nonSubsEvent)\n            return;\n          toggleSubtitleTracks(stateOwners, true);\n        };\n        (_a = media.textTracks) == null ? void 0 : _a.addEventListener(\n          \"addtrack\",\n          updateDefaultSubtitlesCallback\n        );\n        (_b = media.textTracks) == null ? void 0 : _b.addEventListener(\n          \"removetrack\",\n          updateDefaultSubtitlesCallback\n        );\n        updateDefaultSubtitlesCallback();\n        return () => {\n          var _a2, _b2;\n          (_a2 = media.textTracks) == null ? void 0 : _a2.removeEventListener(\n            \"addtrack\",\n            updateDefaultSubtitlesCallback\n          );\n          (_b2 = media.textTracks) == null ? void 0 : _b2.removeEventListener(\n            \"removetrack\",\n            updateDefaultSubtitlesCallback\n          );\n        };\n      }\n    ]\n  },\n  mediaChaptersCues: {\n    get(stateOwners) {\n      var _a;\n      const { media } = stateOwners;\n      if (!media)\n        return [];\n      const [chaptersTrack] = getTextTracksList(media, {\n        kind: TextTrackKinds.CHAPTERS\n      });\n      return Array.from((_a = chaptersTrack == null ? void 0 : chaptersTrack.cues) != null ? _a : []).map(\n        ({ text, startTime, endTime }) => ({\n          text,\n          startTime,\n          endTime\n        })\n      );\n    },\n    mediaEvents: [\"loadstart\", \"loadedmetadata\"],\n    textTracksEvents: [\"addtrack\", \"removetrack\", \"change\"],\n    stateOwnersUpdateHandlers: [\n      (handler, stateOwners) => {\n        var _a;\n        const { media } = stateOwners;\n        if (!media)\n          return;\n        const chaptersTrack = media.querySelector(\n          'track[kind=\"chapters\"][default][src]'\n        );\n        const shadowChaptersTrack = (_a = media.shadowRoot) == null ? void 0 : _a.querySelector(\n          ':is(video,audio) > track[kind=\"chapters\"][default][src]'\n        );\n        chaptersTrack == null ? void 0 : chaptersTrack.addEventListener(\"load\", handler);\n        shadowChaptersTrack == null ? void 0 : shadowChaptersTrack.addEventListener(\"load\", handler);\n        return () => {\n          chaptersTrack == null ? void 0 : chaptersTrack.removeEventListener(\"load\", handler);\n          shadowChaptersTrack == null ? void 0 : shadowChaptersTrack.removeEventListener(\"load\", handler);\n        };\n      }\n    ]\n  },\n  // Modeling state tied to root node\n  mediaIsPip: {\n    get(stateOwners) {\n      var _a, _b;\n      const { media, documentElement } = stateOwners;\n      if (!media || !documentElement)\n        return false;\n      if (!documentElement.pictureInPictureElement)\n        return false;\n      if (documentElement.pictureInPictureElement === media)\n        return true;\n      if (documentElement.pictureInPictureElement instanceof HTMLMediaElement) {\n        if (!((_a = media.localName) == null ? void 0 : _a.includes(\"-\")))\n          return false;\n        return containsComposedNode(\n          media,\n          documentElement.pictureInPictureElement\n        );\n      }\n      if (documentElement.pictureInPictureElement.localName.includes(\"-\")) {\n        let currentRoot = documentElement.pictureInPictureElement.shadowRoot;\n        while (currentRoot == null ? void 0 : currentRoot.pictureInPictureElement) {\n          if (currentRoot.pictureInPictureElement === media)\n            return true;\n          currentRoot = (_b = currentRoot.pictureInPictureElement) == null ? void 0 : _b.shadowRoot;\n        }\n      }\n      return false;\n    },\n    set(value, stateOwners) {\n      const { media } = stateOwners;\n      if (!media)\n        return;\n      if (value) {\n        if (!document.pictureInPictureEnabled) {\n          console.warn(\"MediaChrome: Picture-in-picture is not enabled\");\n          return;\n        }\n        if (!media.requestPictureInPicture) {\n          console.warn(\n            \"MediaChrome: The current media does not support picture-in-picture\"\n          );\n          return;\n        }\n        const warnNotReady = () => {\n          console.warn(\n            \"MediaChrome: The media is not ready for picture-in-picture. It must have a readyState > 0.\"\n          );\n        };\n        media.requestPictureInPicture().catch((err) => {\n          if (err.code === 11) {\n            if (!media.src) {\n              console.warn(\n                \"MediaChrome: The media is not ready for picture-in-picture. It must have a src set.\"\n              );\n              return;\n            }\n            if (media.readyState === 0 && media.preload === \"none\") {\n              const cleanup = () => {\n                media.removeEventListener(\"loadedmetadata\", tryPip);\n                media.preload = \"none\";\n              };\n              const tryPip = () => {\n                media.requestPictureInPicture().catch(warnNotReady);\n                cleanup();\n              };\n              media.addEventListener(\"loadedmetadata\", tryPip);\n              media.preload = \"metadata\";\n              setTimeout(() => {\n                if (media.readyState === 0)\n                  warnNotReady();\n                cleanup();\n              }, 1e3);\n            } else {\n              throw err;\n            }\n          } else {\n            throw err;\n          }\n        });\n      } else if (document.pictureInPictureElement) {\n        document.exitPictureInPicture();\n      }\n    },\n    mediaEvents: [\"enterpictureinpicture\", \"leavepictureinpicture\"]\n  },\n  mediaRenditionList: {\n    get(stateOwners) {\n      var _a;\n      const { media } = stateOwners;\n      return [...(_a = media == null ? void 0 : media.videoRenditions) != null ? _a : []].map((videoRendition) => ({\n        ...videoRendition\n      }));\n    },\n    mediaEvents: [\"emptied\", \"loadstart\"],\n    videoRenditionsEvents: [\"addrendition\", \"removerendition\"]\n  },\n  /** @TODO Model this as a derived value? (CJP) */\n  mediaRenditionSelected: {\n    get(stateOwners) {\n      var _a, _b, _c;\n      const { media } = stateOwners;\n      return (_c = (_b = media == null ? void 0 : media.videoRenditions) == null ? void 0 : _b[(_a = media.videoRenditions) == null ? void 0 : _a.selectedIndex]) == null ? void 0 : _c.id;\n    },\n    set(value, stateOwners) {\n      const { media } = stateOwners;\n      if (!(media == null ? void 0 : media.videoRenditions)) {\n        console.warn(\n          \"MediaController: Rendition selection not supported by this media.\"\n        );\n        return;\n      }\n      const renditionId = value;\n      const index = Array.prototype.findIndex.call(\n        media.videoRenditions,\n        (r) => r.id == renditionId\n      );\n      if (media.videoRenditions.selectedIndex != index) {\n        media.videoRenditions.selectedIndex = index;\n      }\n    },\n    mediaEvents: [\"emptied\"],\n    videoRenditionsEvents: [\"addrendition\", \"removerendition\", \"change\"]\n  },\n  mediaAudioTrackList: {\n    get(stateOwners) {\n      var _a;\n      const { media } = stateOwners;\n      return [...(_a = media == null ? void 0 : media.audioTracks) != null ? _a : []];\n    },\n    mediaEvents: [\"emptied\", \"loadstart\"],\n    audioTracksEvents: [\"addtrack\", \"removetrack\"]\n  },\n  mediaAudioTrackEnabled: {\n    get(stateOwners) {\n      var _a, _b;\n      const { media } = stateOwners;\n      return (_b = [...(_a = media == null ? void 0 : media.audioTracks) != null ? _a : []].find(\n        (audioTrack) => audioTrack.enabled\n      )) == null ? void 0 : _b.id;\n    },\n    set(value, stateOwners) {\n      const { media } = stateOwners;\n      if (!(media == null ? void 0 : media.audioTracks)) {\n        console.warn(\n          \"MediaChrome: Audio track selection not supported by this media.\"\n        );\n        return;\n      }\n      const audioTrackId = value;\n      for (const track of media.audioTracks) {\n        track.enabled = audioTrackId == track.id;\n      }\n    },\n    mediaEvents: [\"emptied\"],\n    audioTracksEvents: [\"addtrack\", \"removetrack\", \"change\"]\n  },\n  mediaIsFullscreen: {\n    get(stateOwners) {\n      return isFullscreen(stateOwners);\n    },\n    set(value, stateOwners) {\n      if (!value) {\n        exitFullscreen(stateOwners);\n      } else {\n        enterFullscreen(stateOwners);\n      }\n    },\n    // older Safari version may require webkit-specific events\n    rootEvents: [\"fullscreenchange\", \"webkitfullscreenchange\"],\n    // iOS requires webkit-specific events on the video.\n    mediaEvents: [\"webkitbeginfullscreen\", \"webkitendfullscreen\", \"webkitpresentationmodechanged\"]\n  },\n  mediaIsCasting: {\n    // Note this relies on a customized castable-video element.\n    get(stateOwners) {\n      var _a;\n      const { media } = stateOwners;\n      if (!(media == null ? void 0 : media.remote) || ((_a = media.remote) == null ? void 0 : _a.state) === \"disconnected\")\n        return false;\n      return !!media.remote.state;\n    },\n    set(value, stateOwners) {\n      var _a, _b;\n      const { media } = stateOwners;\n      if (!media)\n        return;\n      if (value && ((_a = media.remote) == null ? void 0 : _a.state) !== \"disconnected\")\n        return;\n      if (!value && ((_b = media.remote) == null ? void 0 : _b.state) !== \"connected\")\n        return;\n      if (typeof media.remote.prompt !== \"function\") {\n        console.warn(\n          \"MediaChrome: Casting is not supported in this environment\"\n        );\n        return;\n      }\n      media.remote.prompt().catch(() => {\n      });\n    },\n    remoteEvents: [\"connect\", \"connecting\", \"disconnect\"]\n  },\n  // NOTE: Newly added state for tracking airplaying\n  mediaIsAirplaying: {\n    // NOTE: Cannot know if airplaying since Safari doesn't fully support HTMLMediaElement::remote yet (e.g. remote::state) (CJP)\n    get() {\n      return false;\n    },\n    set(_value, stateOwners) {\n      const { media } = stateOwners;\n      if (!media)\n        return;\n      if (!(media.webkitShowPlaybackTargetPicker && globalThis.WebKitPlaybackTargetAvailabilityEvent)) {\n        console.warn(\n          \"MediaChrome: received a request to select AirPlay but AirPlay is not supported in this environment\"\n        );\n        return;\n      }\n      media.webkitShowPlaybackTargetPicker();\n    },\n    mediaEvents: [\"webkitcurrentplaybacktargetiswirelesschanged\"]\n  },\n  mediaFullscreenUnavailable: {\n    get(stateOwners) {\n      const { media } = stateOwners;\n      if (!fullscreenSupported || !hasFullscreenSupport(media))\n        return AvailabilityStates.UNSUPPORTED;\n      return void 0;\n    }\n  },\n  mediaPipUnavailable: {\n    get(stateOwners) {\n      const { media } = stateOwners;\n      if (!pipSupported || !hasPipSupport(media))\n        return AvailabilityStates.UNSUPPORTED;\n    }\n  },\n  mediaVolumeUnavailable: {\n    get(stateOwners) {\n      const { media } = stateOwners;\n      if (volumeSupported === false || (media == null ? void 0 : media.volume) == void 0) {\n        return AvailabilityStates.UNSUPPORTED;\n      }\n      return void 0;\n    },\n    // NOTE: Slightly different impl here. Added generic support for\n    // \"stateOwnersUpdateHandlers\" since the original impl had to hack around\n    // race conditions. (CJP)\n    stateOwnersUpdateHandlers: [\n      (handler) => {\n        if (volumeSupported == null) {\n          volumeSupportPromise.then(\n            (supported) => handler(supported ? void 0 : AvailabilityStates.UNSUPPORTED)\n          );\n        }\n      }\n    ]\n  },\n  mediaCastUnavailable: {\n    // @ts-ignore\n    get(stateOwners, { availability = \"not-available\" } = {}) {\n      var _a;\n      const { media } = stateOwners;\n      if (!castSupported || !((_a = media == null ? void 0 : media.remote) == null ? void 0 : _a.state)) {\n        return AvailabilityStates.UNSUPPORTED;\n      }\n      if (availability == null || availability === \"available\")\n        return void 0;\n      return AvailabilityStates.UNAVAILABLE;\n    },\n    stateOwnersUpdateHandlers: [\n      (handler, stateOwners) => {\n        var _a;\n        const { media } = stateOwners;\n        if (!media)\n          return;\n        const remotePlaybackDisabled = media.disableRemotePlayback || media.hasAttribute(\"disableremoteplayback\");\n        if (!remotePlaybackDisabled) {\n          (_a = media == null ? void 0 : media.remote) == null ? void 0 : _a.watchAvailability((availabilityBool) => {\n            const availability = availabilityBool ? \"available\" : \"not-available\";\n            handler({ availability });\n          }).catch((error) => {\n            if (error.name === \"NotSupportedError\") {\n              handler({ availability: null });\n            } else {\n              handler({ availability: \"not-available\" });\n            }\n          });\n        }\n        return () => {\n          var _a2;\n          (_a2 = media == null ? void 0 : media.remote) == null ? void 0 : _a2.cancelWatchAvailability().catch(() => {\n          });\n        };\n      }\n    ]\n  },\n  mediaAirplayUnavailable: {\n    get(_stateOwners, event) {\n      if (!airplaySupported)\n        return AvailabilityStates.UNSUPPORTED;\n      if ((event == null ? void 0 : event.availability) === \"not-available\") {\n        return AvailabilityStates.UNAVAILABLE;\n      }\n      return void 0;\n    },\n    // NOTE: Keeping this event, as it's still the documented way of monitoring\n    // for AirPlay availability from Apple.\n    // See: https://developer.apple.com/documentation/webkitjs/adding_an_airplay_button_to_your_safari_media_controls#2940021 (CJP)\n    mediaEvents: [\"webkitplaybacktargetavailabilitychanged\"],\n    stateOwnersUpdateHandlers: [\n      (handler, stateOwners) => {\n        var _a;\n        const { media } = stateOwners;\n        if (!media)\n          return;\n        const remotePlaybackDisabled = media.disableRemotePlayback || media.hasAttribute(\"disableremoteplayback\");\n        if (!remotePlaybackDisabled) {\n          (_a = media == null ? void 0 : media.remote) == null ? void 0 : _a.watchAvailability((availabilityBool) => {\n            const availability = availabilityBool ? \"available\" : \"not-available\";\n            handler({ availability });\n          }).catch((error) => {\n            if (error.name === \"NotSupportedError\") {\n              handler({ availability: null });\n            } else {\n              handler({ availability: \"not-available\" });\n            }\n          });\n        }\n        return () => {\n          var _a2;\n          (_a2 = media == null ? void 0 : media.remote) == null ? void 0 : _a2.cancelWatchAvailability().catch(() => {\n          });\n        };\n      }\n    ]\n  },\n  mediaRenditionUnavailable: {\n    get(stateOwners) {\n      var _a;\n      const { media } = stateOwners;\n      if (!(media == null ? void 0 : media.videoRenditions)) {\n        return AvailabilityStates.UNSUPPORTED;\n      }\n      if (!((_a = media.videoRenditions) == null ? void 0 : _a.length)) {\n        return AvailabilityStates.UNAVAILABLE;\n      }\n      return void 0;\n    },\n    mediaEvents: [\"emptied\", \"loadstart\"],\n    videoRenditionsEvents: [\"addrendition\", \"removerendition\"]\n  },\n  mediaAudioTrackUnavailable: {\n    get(stateOwners) {\n      var _a, _b;\n      const { media } = stateOwners;\n      if (!(media == null ? void 0 : media.audioTracks)) {\n        return AvailabilityStates.UNSUPPORTED;\n      }\n      if (((_b = (_a = media.audioTracks) == null ? void 0 : _a.length) != null ? _b : 0) <= 1) {\n        return AvailabilityStates.UNAVAILABLE;\n      }\n      return void 0;\n    },\n    mediaEvents: [\"emptied\", \"loadstart\"],\n    audioTracksEvents: [\"addtrack\", \"removetrack\"]\n  }\n};\nexport {\n  prepareStateOwners,\n  stateMediator,\n  volumeSupportPromise\n};\n", "import { globalThis } from \"../utils/server-safe-globals.js\";\nimport {\n  MediaUIEvents,\n  StreamTypes,\n  TextTrackKinds,\n  TextTrackModes\n} from \"../constants.js\";\nimport {\n  getTextTracksList,\n  parseTracks,\n  updateTracksModeTo\n} from \"../utils/captions.js\";\nimport { getSubtitleTracks, toggleSubtitleTracks } from \"./util.js\";\nconst requestMap = {\n  /**\n   * @TODO Consider adding state to `StateMediator` for e.g. `mediaThumbnailCues` and use that for derived state here (CJP)\n   */\n  [MediaUIEvents.MEDIA_PREVIEW_REQUEST](stateMediator, stateOwners, { detail }) {\n    var _a, _b, _c;\n    const { media } = stateOwners;\n    const mediaPreviewTime = detail != null ? detail : void 0;\n    let mediaPreviewImage = void 0;\n    let mediaPreviewCoords = void 0;\n    if (media && mediaPreviewTime != null) {\n      const [track] = getTextTracksList(media, {\n        kind: TextTrackKinds.METADATA,\n        label: \"thumbnails\"\n      });\n      const cue = Array.prototype.find.call((_a = track == null ? void 0 : track.cues) != null ? _a : [], (c, i, cs) => {\n        if (i === 0)\n          return c.endTime > mediaPreviewTime;\n        if (i === cs.length - 1)\n          return c.startTime <= mediaPreviewTime;\n        return c.startTime <= mediaPreviewTime && c.endTime > mediaPreviewTime;\n      });\n      if (cue) {\n        const base = !/'^(?:[a-z]+:)?\\/\\//i.test(cue.text) ? (_b = media == null ? void 0 : media.querySelector(\n          'track[label=\"thumbnails\"]'\n        )) == null ? void 0 : _b.src : void 0;\n        const url = new URL(cue.text, base);\n        const previewCoordsStr = new URLSearchParams(url.hash).get(\"#xywh\");\n        mediaPreviewCoords = previewCoordsStr.split(\",\").map((numStr) => +numStr);\n        mediaPreviewImage = url.href;\n      }\n    }\n    const mediaDuration = stateMediator.mediaDuration.get(stateOwners);\n    const mediaChaptersCues = stateMediator.mediaChaptersCues.get(stateOwners);\n    let mediaPreviewChapter = (_c = mediaChaptersCues.find((c, i, cs) => {\n      if (i === cs.length - 1 && mediaDuration === c.endTime) {\n        return c.startTime <= mediaPreviewTime && c.endTime >= mediaPreviewTime;\n      }\n      return c.startTime <= mediaPreviewTime && c.endTime > mediaPreviewTime;\n    })) == null ? void 0 : _c.text;\n    if (detail != null && mediaPreviewChapter == null) {\n      mediaPreviewChapter = \"\";\n    }\n    return {\n      mediaPreviewTime,\n      mediaPreviewImage,\n      mediaPreviewCoords,\n      mediaPreviewChapter\n    };\n  },\n  [MediaUIEvents.MEDIA_PAUSE_REQUEST](stateMediator, stateOwners) {\n    const key = \"mediaPaused\";\n    const value = true;\n    stateMediator[key].set(value, stateOwners);\n  },\n  [MediaUIEvents.MEDIA_PLAY_REQUEST](stateMediator, stateOwners) {\n    var _a;\n    const key = \"mediaPaused\";\n    const value = false;\n    const live = stateMediator.mediaStreamType.get(stateOwners) === StreamTypes.LIVE;\n    if (live) {\n      const notDvr = !(stateMediator.mediaTargetLiveWindow.get(stateOwners) > 0);\n      const liveEdgeTime = (_a = stateMediator.mediaSeekable.get(stateOwners)) == null ? void 0 : _a[1];\n      if (notDvr && liveEdgeTime) {\n        stateMediator.mediaCurrentTime.set(liveEdgeTime, stateOwners);\n      }\n    }\n    stateMediator[key].set(value, stateOwners);\n  },\n  [MediaUIEvents.MEDIA_PLAYBACK_RATE_REQUEST](stateMediator, stateOwners, { detail }) {\n    const key = \"mediaPlaybackRate\";\n    const value = detail;\n    stateMediator[key].set(value, stateOwners);\n  },\n  [MediaUIEvents.MEDIA_MUTE_REQUEST](stateMediator, stateOwners) {\n    const key = \"mediaMuted\";\n    const value = true;\n    stateMediator[key].set(value, stateOwners);\n  },\n  [MediaUIEvents.MEDIA_UNMUTE_REQUEST](stateMediator, stateOwners) {\n    const key = \"mediaMuted\";\n    const value = false;\n    if (!stateMediator.mediaVolume.get(stateOwners)) {\n      stateMediator.mediaVolume.set(0.25, stateOwners);\n    }\n    stateMediator[key].set(value, stateOwners);\n  },\n  [MediaUIEvents.MEDIA_VOLUME_REQUEST](stateMediator, stateOwners, { detail }) {\n    const key = \"mediaVolume\";\n    const value = detail;\n    if (value && stateMediator.mediaMuted.get(stateOwners)) {\n      stateMediator.mediaMuted.set(false, stateOwners);\n    }\n    stateMediator[key].set(value, stateOwners);\n  },\n  [MediaUIEvents.MEDIA_SEEK_REQUEST](stateMediator, stateOwners, { detail }) {\n    const key = \"mediaCurrentTime\";\n    const value = detail;\n    stateMediator[key].set(value, stateOwners);\n  },\n  [MediaUIEvents.MEDIA_SEEK_TO_LIVE_REQUEST](stateMediator, stateOwners) {\n    var _a;\n    const key = \"mediaCurrentTime\";\n    const value = (_a = stateMediator.mediaSeekable.get(stateOwners)) == null ? void 0 : _a[1];\n    if (Number.isNaN(Number(value)))\n      return;\n    stateMediator[key].set(value, stateOwners);\n  },\n  // Text Tracks state change requests\n  [MediaUIEvents.MEDIA_SHOW_SUBTITLES_REQUEST](_stateMediator, stateOwners, { detail }) {\n    var _a;\n    const { options } = stateOwners;\n    const tracks = getSubtitleTracks(stateOwners);\n    const tracksToUpdate = parseTracks(detail);\n    const preferredLanguage = (_a = tracksToUpdate[0]) == null ? void 0 : _a.language;\n    if (preferredLanguage && !options.noSubtitlesLangPref) {\n      globalThis.localStorage.setItem(\n        \"media-chrome-pref-subtitles-lang\",\n        preferredLanguage\n      );\n    }\n    updateTracksModeTo(TextTrackModes.SHOWING, tracks, tracksToUpdate);\n  },\n  [MediaUIEvents.MEDIA_DISABLE_SUBTITLES_REQUEST](_stateMediator, stateOwners, { detail }) {\n    const tracks = getSubtitleTracks(stateOwners);\n    const tracksToUpdate = detail != null ? detail : [];\n    updateTracksModeTo(TextTrackModes.DISABLED, tracks, tracksToUpdate);\n  },\n  [MediaUIEvents.MEDIA_TOGGLE_SUBTITLES_REQUEST](_stateMediator, stateOwners, { detail }) {\n    toggleSubtitleTracks(stateOwners, detail);\n  },\n  // Renditions/Tracks state change requests\n  [MediaUIEvents.MEDIA_RENDITION_REQUEST](stateMediator, stateOwners, { detail }) {\n    const key = \"mediaRenditionSelected\";\n    const value = detail;\n    stateMediator[key].set(value, stateOwners);\n  },\n  [MediaUIEvents.MEDIA_AUDIO_TRACK_REQUEST](stateMediator, stateOwners, { detail }) {\n    const key = \"mediaAudioTrackEnabled\";\n    const value = detail;\n    stateMediator[key].set(value, stateOwners);\n  },\n  // State change requests dependent on root node\n  [MediaUIEvents.MEDIA_ENTER_PIP_REQUEST](stateMediator, stateOwners) {\n    const key = \"mediaIsPip\";\n    const value = true;\n    if (stateMediator.mediaIsFullscreen.get(stateOwners)) {\n      stateMediator.mediaIsFullscreen.set(false, stateOwners);\n    }\n    stateMediator[key].set(value, stateOwners);\n  },\n  [MediaUIEvents.MEDIA_EXIT_PIP_REQUEST](stateMediator, stateOwners) {\n    const key = \"mediaIsPip\";\n    const value = false;\n    stateMediator[key].set(value, stateOwners);\n  },\n  [MediaUIEvents.MEDIA_ENTER_FULLSCREEN_REQUEST](stateMediator, stateOwners) {\n    const key = \"mediaIsFullscreen\";\n    const value = true;\n    if (stateMediator.mediaIsPip.get(stateOwners)) {\n      stateMediator.mediaIsPip.set(false, stateOwners);\n    }\n    stateMediator[key].set(value, stateOwners);\n  },\n  [MediaUIEvents.MEDIA_EXIT_FULLSCREEN_REQUEST](stateMediator, stateOwners) {\n    const key = \"mediaIsFullscreen\";\n    const value = false;\n    stateMediator[key].set(value, stateOwners);\n  },\n  [MediaUIEvents.MEDIA_ENTER_CAST_REQUEST](stateMediator, stateOwners) {\n    const key = \"mediaIsCasting\";\n    const value = true;\n    if (stateMediator.mediaIsFullscreen.get(stateOwners)) {\n      stateMediator.mediaIsFullscreen.set(false, stateOwners);\n    }\n    stateMediator[key].set(value, stateOwners);\n  },\n  [MediaUIEvents.MEDIA_EXIT_CAST_REQUEST](stateMediator, stateOwners) {\n    const key = \"mediaIsCasting\";\n    const value = false;\n    stateMediator[key].set(value, stateOwners);\n  },\n  [MediaUIEvents.MEDIA_AIRPLAY_REQUEST](stateMediator, stateOwners) {\n    const key = \"mediaIsAirplaying\";\n    const value = true;\n    stateMediator[key].set(value, stateOwners);\n  }\n};\nexport {\n  requestMap\n};\n", "import {\n  stateMediator as defaultStateMediator,\n  prepareStateOwners\n} from \"./state-mediator.js\";\nimport { areValuesEq } from \"./util.js\";\nimport { requestMap as defaultRequestMap } from \"./request-map.js\";\nconst createMediaStore = ({\n  media,\n  fullscreenElement,\n  documentElement,\n  stateMediator = defaultStateMediator,\n  requestMap = defaultRequestMap,\n  options = {},\n  monitorStateOwnersOnlyWithSubscriptions = true\n}) => {\n  const callbacks = [];\n  const stateOwners = {\n    // Spreading options here since folks should not rely on holding onto references\n    // for any app-level logic wrt options.\n    options: { ...options }\n  };\n  let state = Object.freeze({\n    mediaPreviewTime: void 0,\n    mediaPreviewImage: void 0,\n    mediaPreviewCoords: void 0,\n    mediaPreviewChapter: void 0\n  });\n  const updateState = (nextStateDelta) => {\n    if (nextStateDelta == void 0)\n      return;\n    if (areValuesEq(nextStateDelta, state)) {\n      return;\n    }\n    state = Object.freeze({\n      ...state,\n      ...nextStateDelta\n    });\n    callbacks.forEach((cb) => cb(state));\n  };\n  const updateStateFromFacade = () => {\n    const nextState = Object.entries(stateMediator).reduce(\n      (nextState2, [stateName, { get }]) => {\n        nextState2[stateName] = get(stateOwners);\n        return nextState2;\n      },\n      {}\n    );\n    updateState(nextState);\n  };\n  const stateUpdateHandlers = {};\n  let nextStateOwners = void 0;\n  const updateStateOwners = async (nextStateOwnersDelta, nextSubscriberCount) => {\n    var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;\n    const pendingUpdate = !!nextStateOwners;\n    nextStateOwners = {\n      ...stateOwners,\n      ...nextStateOwners != null ? nextStateOwners : {},\n      ...nextStateOwnersDelta\n    };\n    if (pendingUpdate)\n      return;\n    await prepareStateOwners(...Object.values(nextStateOwnersDelta));\n    const shouldTeardownFromSubscriberCount = callbacks.length > 0 && nextSubscriberCount === 0 && monitorStateOwnersOnlyWithSubscriptions;\n    const mediaChanged = stateOwners.media !== nextStateOwners.media;\n    const textTracksChanged = ((_a = stateOwners.media) == null ? void 0 : _a.textTracks) !== ((_b = nextStateOwners.media) == null ? void 0 : _b.textTracks);\n    const videoRenditionsChanged = ((_c = stateOwners.media) == null ? void 0 : _c.videoRenditions) !== ((_d = nextStateOwners.media) == null ? void 0 : _d.videoRenditions);\n    const audioTracksChanged = ((_e = stateOwners.media) == null ? void 0 : _e.audioTracks) !== ((_f = nextStateOwners.media) == null ? void 0 : _f.audioTracks);\n    const remoteChanged = ((_g = stateOwners.media) == null ? void 0 : _g.remote) !== ((_h = nextStateOwners.media) == null ? void 0 : _h.remote);\n    const rootNodeChanged = stateOwners.documentElement !== nextStateOwners.documentElement;\n    const teardownMedia = !!stateOwners.media && (mediaChanged || shouldTeardownFromSubscriberCount);\n    const teardownTextTracks = !!((_i = stateOwners.media) == null ? void 0 : _i.textTracks) && (textTracksChanged || shouldTeardownFromSubscriberCount);\n    const teardownVideoRenditions = !!((_j = stateOwners.media) == null ? void 0 : _j.videoRenditions) && (videoRenditionsChanged || shouldTeardownFromSubscriberCount);\n    const teardownAudioTracks = !!((_k = stateOwners.media) == null ? void 0 : _k.audioTracks) && (audioTracksChanged || shouldTeardownFromSubscriberCount);\n    const teardownRemote = !!((_l = stateOwners.media) == null ? void 0 : _l.remote) && (remoteChanged || shouldTeardownFromSubscriberCount);\n    const teardownRootNode = !!stateOwners.documentElement && (rootNodeChanged || shouldTeardownFromSubscriberCount);\n    const teardownSomething = teardownMedia || teardownTextTracks || teardownVideoRenditions || teardownAudioTracks || teardownRemote || teardownRootNode;\n    const shouldSetupFromSubscriberCount = callbacks.length === 0 && nextSubscriberCount === 1 && monitorStateOwnersOnlyWithSubscriptions;\n    const setupMedia = !!nextStateOwners.media && (mediaChanged || shouldSetupFromSubscriberCount);\n    const setupTextTracks = !!((_m = nextStateOwners.media) == null ? void 0 : _m.textTracks) && (textTracksChanged || shouldSetupFromSubscriberCount);\n    const setupVideoRenditions = !!((_n = nextStateOwners.media) == null ? void 0 : _n.videoRenditions) && (videoRenditionsChanged || shouldSetupFromSubscriberCount);\n    const setupAudioTracks = !!((_o = nextStateOwners.media) == null ? void 0 : _o.audioTracks) && (audioTracksChanged || shouldSetupFromSubscriberCount);\n    const setupRemote = !!((_p = nextStateOwners.media) == null ? void 0 : _p.remote) && (remoteChanged || shouldSetupFromSubscriberCount);\n    const setupRootNode = !!nextStateOwners.documentElement && (rootNodeChanged || shouldSetupFromSubscriberCount);\n    const setupSomething = setupMedia || setupTextTracks || setupVideoRenditions || setupAudioTracks || setupRemote || setupRootNode;\n    const somethingToDo = teardownSomething || setupSomething;\n    if (!somethingToDo) {\n      Object.entries(nextStateOwners).forEach(\n        ([stateOwnerName, stateOwner]) => {\n          stateOwners[stateOwnerName] = stateOwner;\n        }\n      );\n      updateStateFromFacade();\n      nextStateOwners = void 0;\n      return;\n    }\n    Object.entries(stateMediator).forEach(\n      ([\n        stateName,\n        {\n          get,\n          mediaEvents = [],\n          textTracksEvents = [],\n          videoRenditionsEvents = [],\n          audioTracksEvents = [],\n          remoteEvents = [],\n          rootEvents = [],\n          stateOwnersUpdateHandlers = []\n        }\n      ]) => {\n        if (!stateUpdateHandlers[stateName]) {\n          stateUpdateHandlers[stateName] = {};\n        }\n        const handler = (event) => {\n          const nextValue = get(stateOwners, event);\n          updateState({ [stateName]: nextValue });\n        };\n        let prevHandler;\n        prevHandler = stateUpdateHandlers[stateName].mediaEvents;\n        mediaEvents.forEach((eventType) => {\n          if (prevHandler && teardownMedia) {\n            stateOwners.media.removeEventListener(eventType, prevHandler);\n            stateUpdateHandlers[stateName].mediaEvents = void 0;\n          }\n          if (setupMedia) {\n            nextStateOwners.media.addEventListener(eventType, handler);\n            stateUpdateHandlers[stateName].mediaEvents = handler;\n          }\n        });\n        prevHandler = stateUpdateHandlers[stateName].textTracksEvents;\n        textTracksEvents.forEach((eventType) => {\n          var _a2, _b2;\n          if (prevHandler && teardownTextTracks) {\n            (_a2 = stateOwners.media.textTracks) == null ? void 0 : _a2.removeEventListener(\n              eventType,\n              prevHandler\n            );\n            stateUpdateHandlers[stateName].textTracksEvents = void 0;\n          }\n          if (setupTextTracks) {\n            (_b2 = nextStateOwners.media.textTracks) == null ? void 0 : _b2.addEventListener(\n              eventType,\n              handler\n            );\n            stateUpdateHandlers[stateName].textTracksEvents = handler;\n          }\n        });\n        prevHandler = stateUpdateHandlers[stateName].videoRenditionsEvents;\n        videoRenditionsEvents.forEach((eventType) => {\n          var _a2, _b2;\n          if (prevHandler && teardownVideoRenditions) {\n            (_a2 = stateOwners.media.videoRenditions) == null ? void 0 : _a2.removeEventListener(\n              eventType,\n              prevHandler\n            );\n            stateUpdateHandlers[stateName].videoRenditionsEvents = void 0;\n          }\n          if (setupVideoRenditions) {\n            (_b2 = nextStateOwners.media.videoRenditions) == null ? void 0 : _b2.addEventListener(\n              eventType,\n              handler\n            );\n            stateUpdateHandlers[stateName].videoRenditionsEvents = handler;\n          }\n        });\n        prevHandler = stateUpdateHandlers[stateName].audioTracksEvents;\n        audioTracksEvents.forEach((eventType) => {\n          var _a2, _b2;\n          if (prevHandler && teardownAudioTracks) {\n            (_a2 = stateOwners.media.audioTracks) == null ? void 0 : _a2.removeEventListener(\n              eventType,\n              prevHandler\n            );\n            stateUpdateHandlers[stateName].audioTracksEvents = void 0;\n          }\n          if (setupAudioTracks) {\n            (_b2 = nextStateOwners.media.audioTracks) == null ? void 0 : _b2.addEventListener(\n              eventType,\n              handler\n            );\n            stateUpdateHandlers[stateName].audioTracksEvents = handler;\n          }\n        });\n        prevHandler = stateUpdateHandlers[stateName].remoteEvents;\n        remoteEvents.forEach((eventType) => {\n          var _a2, _b2;\n          if (prevHandler && teardownRemote) {\n            (_a2 = stateOwners.media.remote) == null ? void 0 : _a2.removeEventListener(\n              eventType,\n              prevHandler\n            );\n            stateUpdateHandlers[stateName].remoteEvents = void 0;\n          }\n          if (setupRemote) {\n            (_b2 = nextStateOwners.media.remote) == null ? void 0 : _b2.addEventListener(eventType, handler);\n            stateUpdateHandlers[stateName].remoteEvents = handler;\n          }\n        });\n        prevHandler = stateUpdateHandlers[stateName].rootEvents;\n        rootEvents.forEach((eventType) => {\n          if (prevHandler && teardownRootNode) {\n            stateOwners.documentElement.removeEventListener(\n              eventType,\n              prevHandler\n            );\n            stateUpdateHandlers[stateName].rootEvents = void 0;\n          }\n          if (setupRootNode) {\n            nextStateOwners.documentElement.addEventListener(\n              eventType,\n              handler\n            );\n            stateUpdateHandlers[stateName].rootEvents = handler;\n          }\n        });\n        const prevHandlerTeardown = stateUpdateHandlers[stateName].stateOwnersUpdateHandlers;\n        stateOwnersUpdateHandlers.forEach((fn) => {\n          if (prevHandlerTeardown && teardownSomething) {\n            prevHandlerTeardown();\n          }\n          if (setupSomething) {\n            stateUpdateHandlers[stateName].stateOwnersUpdateHandlers = fn(\n              handler,\n              nextStateOwners\n            );\n          }\n        });\n      }\n    );\n    Object.entries(nextStateOwners).forEach(([stateOwnerName, stateOwner]) => {\n      stateOwners[stateOwnerName] = stateOwner;\n    });\n    updateStateFromFacade();\n    nextStateOwners = void 0;\n  };\n  updateStateOwners({ media, fullscreenElement, documentElement, options });\n  return {\n    // note that none of these cases directly interact with the media element, root node, full screen element, etc.\n    // note these \"actions\" could just be the events if we wanted, especially if we normalize on \"detail\" for\n    // any payload-relevant values\n    // This is roughly equivalent to our used to be in our state requests dictionary object, though much of the\n    // \"heavy lifting\" is now moved into the facade `set()`\n    dispatch(action) {\n      const { type, detail } = action;\n      if (requestMap[type]) {\n        updateState(requestMap[type](stateMediator, stateOwners, action));\n        return;\n      }\n      if (type === \"mediaelementchangerequest\") {\n        updateStateOwners({ media: detail });\n      } else if (type === \"fullscreenelementchangerequest\") {\n        updateStateOwners({ fullscreenElement: detail });\n      } else if (type === \"documentelementchangerequest\") {\n        updateStateOwners({ documentElement: detail });\n      } else if (type === \"optionschangerequest\") {\n        Object.entries(detail != null ? detail : {}).forEach(([optionName, optionValue]) => {\n          stateOwners.options[optionName] = optionValue;\n        });\n      }\n    },\n    getState() {\n      return state;\n    },\n    subscribe(callback) {\n      updateStateOwners({}, callbacks.length + 1);\n      callbacks.push(callback);\n      callback(state);\n      return () => {\n        const idx = callbacks.indexOf(callback);\n        if (idx >= 0) {\n          updateStateOwners({}, callbacks.length - 1);\n          callbacks.splice(idx, 1);\n        }\n      };\n    }\n  };\n};\nvar media_store_default = createMediaStore;\nexport {\n  media_store_default as default\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar __privateSet = (obj, member, value, setter) => {\n  __accessCheck(obj, member, \"write to private field\");\n  setter ? setter.call(obj, value) : member.set(obj, value);\n  return value;\n};\nvar __privateMethod = (obj, member, method) => {\n  __accessCheck(obj, member, \"access private method\");\n  return method;\n};\nvar _hotKeys, _fullscreenElement, _mediaStore, _mediaStateCallback, _mediaStoreUnsubscribe, _mediaStateEventHandler, _setupDefaultStore, setupDefaultStore_fn, _keyUpHandler, keyUpHandler_fn, _keyDownHandler, keyDownHandler_fn;\nimport { MediaContainer } from \"./media-container.js\";\nimport { document, globalThis } from \"./utils/server-safe-globals.js\";\nimport { AttributeTokenList } from \"./utils/attribute-token-list.js\";\nimport {\n  delay,\n  stringifyRenditionList,\n  stringifyAudioTrackList\n} from \"./utils/utils.js\";\nimport { stringifyTextTrackList } from \"./utils/captions.js\";\nimport {\n  MediaUIEvents,\n  MediaUIAttributes,\n  MediaStateReceiverAttributes,\n  AttributeToStateChangeEventMap,\n  MediaUIProps\n} from \"./constants.js\";\nimport {\n  setBooleanAttr,\n  setNumericAttr,\n  setStringAttr\n} from \"./utils/element-utils.js\";\nimport createMediaStore from \"./media-store/media-store.js\";\nconst ButtonPressedKeys = [\n  \"ArrowLeft\",\n  \"ArrowRight\",\n  \"Enter\",\n  \" \",\n  \"f\",\n  \"m\",\n  \"k\",\n  \"c\"\n];\nconst DEFAULT_SEEK_OFFSET = 10;\nconst Attributes = {\n  DEFAULT_SUBTITLES: \"defaultsubtitles\",\n  DEFAULT_STREAM_TYPE: \"defaultstreamtype\",\n  DEFAULT_DURATION: \"defaultduration\",\n  FULLSCREEN_ELEMENT: \"fullscreenelement\",\n  HOTKEYS: \"hotkeys\",\n  KEYS_USED: \"keysused\",\n  LIVE_EDGE_OFFSET: \"liveedgeoffset\",\n  NO_AUTO_SEEK_TO_LIVE: \"noautoseektolive\",\n  NO_HOTKEYS: \"nohotkeys\",\n  NO_VOLUME_PREF: \"novolumepref\",\n  NO_SUBTITLES_LANG_PREF: \"nosubtitleslangpref\",\n  NO_DEFAULT_STORE: \"nodefaultstore\",\n  KEYBOARD_FORWARD_SEEK_OFFSET: \"keyboardforwardseekoffset\",\n  KEYBOARD_BACKWARD_SEEK_OFFSET: \"keyboardbackwardseekoffset\"\n};\nclass MediaController extends MediaContainer {\n  constructor() {\n    super();\n    __privateAdd(this, _setupDefaultStore);\n    __privateAdd(this, _keyUpHandler);\n    __privateAdd(this, _keyDownHandler);\n    this.mediaStateReceivers = [];\n    this.associatedElementSubscriptions = /* @__PURE__ */ new Map();\n    __privateAdd(this, _hotKeys, new AttributeTokenList(this, Attributes.HOTKEYS));\n    __privateAdd(this, _fullscreenElement, void 0);\n    __privateAdd(this, _mediaStore, void 0);\n    __privateAdd(this, _mediaStateCallback, void 0);\n    __privateAdd(this, _mediaStoreUnsubscribe, void 0);\n    __privateAdd(this, _mediaStateEventHandler, (event) => {\n      var _a;\n      (_a = __privateGet(this, _mediaStore)) == null ? void 0 : _a.dispatch(event);\n    });\n    this.associateElement(this);\n    let prevState = {};\n    __privateSet(this, _mediaStateCallback, (nextState) => {\n      Object.entries(nextState).forEach(([stateName, stateValue]) => {\n        if (stateName in prevState && prevState[stateName] === stateValue)\n          return;\n        this.propagateMediaState(stateName, stateValue);\n        const attrName = stateName.toLowerCase();\n        const evt = new globalThis.CustomEvent(\n          AttributeToStateChangeEventMap[attrName],\n          { composed: true, detail: stateValue }\n        );\n        this.dispatchEvent(evt);\n      });\n      prevState = nextState;\n    });\n    this.enableHotkeys();\n  }\n  static get observedAttributes() {\n    return super.observedAttributes.concat(\n      Attributes.NO_HOTKEYS,\n      Attributes.HOTKEYS,\n      Attributes.DEFAULT_STREAM_TYPE,\n      Attributes.DEFAULT_SUBTITLES,\n      Attributes.DEFAULT_DURATION\n    );\n  }\n  get mediaStore() {\n    return __privateGet(this, _mediaStore);\n  }\n  set mediaStore(value) {\n    var _a, _b;\n    if (__privateGet(this, _mediaStore)) {\n      (_a = __privateGet(this, _mediaStoreUnsubscribe)) == null ? void 0 : _a.call(this);\n      __privateSet(this, _mediaStoreUnsubscribe, void 0);\n    }\n    __privateSet(this, _mediaStore, value);\n    if (!__privateGet(this, _mediaStore) && !this.hasAttribute(Attributes.NO_DEFAULT_STORE)) {\n      __privateMethod(this, _setupDefaultStore, setupDefaultStore_fn).call(this);\n      return;\n    }\n    __privateSet(this, _mediaStoreUnsubscribe, (_b = __privateGet(this, _mediaStore)) == null ? void 0 : _b.subscribe(\n      __privateGet(this, _mediaStateCallback)\n    ));\n  }\n  get fullscreenElement() {\n    var _a;\n    return (_a = __privateGet(this, _fullscreenElement)) != null ? _a : this;\n  }\n  set fullscreenElement(element) {\n    var _a;\n    if (this.hasAttribute(Attributes.FULLSCREEN_ELEMENT)) {\n      this.removeAttribute(Attributes.FULLSCREEN_ELEMENT);\n    }\n    __privateSet(this, _fullscreenElement, element);\n    (_a = __privateGet(this, _mediaStore)) == null ? void 0 : _a.dispatch({\n      type: \"fullscreenelementchangerequest\",\n      detail: this.fullscreenElement\n    });\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    var _a, _b, _c, _d, _e, _f;\n    super.attributeChangedCallback(attrName, oldValue, newValue);\n    if (attrName === Attributes.NO_HOTKEYS) {\n      if (newValue !== oldValue && newValue === \"\") {\n        if (this.hasAttribute(Attributes.HOTKEYS)) {\n          console.warn(\n            \"Media Chrome: Both `hotkeys` and `nohotkeys` have been set. All hotkeys will be disabled.\"\n          );\n        }\n        this.disableHotkeys();\n      } else if (newValue !== oldValue && newValue === null) {\n        this.enableHotkeys();\n      }\n    } else if (attrName === Attributes.HOTKEYS) {\n      __privateGet(this, _hotKeys).value = newValue;\n    } else if (attrName === Attributes.DEFAULT_SUBTITLES && newValue !== oldValue) {\n      (_a = __privateGet(this, _mediaStore)) == null ? void 0 : _a.dispatch({\n        type: \"optionschangerequest\",\n        detail: {\n          defaultSubtitles: this.hasAttribute(Attributes.DEFAULT_SUBTITLES)\n        }\n      });\n    } else if (attrName === Attributes.DEFAULT_STREAM_TYPE) {\n      (_c = __privateGet(this, _mediaStore)) == null ? void 0 : _c.dispatch({\n        type: \"optionschangerequest\",\n        detail: {\n          defaultStreamType: (_b = this.getAttribute(Attributes.DEFAULT_STREAM_TYPE)) != null ? _b : void 0\n        }\n      });\n    } else if (attrName === Attributes.LIVE_EDGE_OFFSET) {\n      (_d = __privateGet(this, _mediaStore)) == null ? void 0 : _d.dispatch({\n        type: \"optionschangerequest\",\n        detail: {\n          liveEdgeOffset: this.hasAttribute(Attributes.LIVE_EDGE_OFFSET) ? +this.getAttribute(Attributes.LIVE_EDGE_OFFSET) : void 0\n        }\n      });\n    } else if (attrName === Attributes.FULLSCREEN_ELEMENT) {\n      const el = newValue ? (_e = this.getRootNode()) == null ? void 0 : _e.getElementById(newValue) : void 0;\n      __privateSet(this, _fullscreenElement, el);\n      (_f = __privateGet(this, _mediaStore)) == null ? void 0 : _f.dispatch({\n        type: \"fullscreenelementchangerequest\",\n        detail: this.fullscreenElement\n      });\n    }\n  }\n  connectedCallback() {\n    var _a, _b;\n    if (!__privateGet(this, _mediaStore) && !this.hasAttribute(Attributes.NO_DEFAULT_STORE)) {\n      __privateMethod(this, _setupDefaultStore, setupDefaultStore_fn).call(this);\n    }\n    (_a = __privateGet(this, _mediaStore)) == null ? void 0 : _a.dispatch({\n      type: \"documentelementchangerequest\",\n      detail: document\n    });\n    super.connectedCallback();\n    if (__privateGet(this, _mediaStore) && !__privateGet(this, _mediaStoreUnsubscribe)) {\n      __privateSet(this, _mediaStoreUnsubscribe, (_b = __privateGet(this, _mediaStore)) == null ? void 0 : _b.subscribe(\n        __privateGet(this, _mediaStateCallback)\n      ));\n    }\n    this.enableHotkeys();\n  }\n  disconnectedCallback() {\n    var _a, _b, _c, _d;\n    (_a = super.disconnectedCallback) == null ? void 0 : _a.call(this);\n    if (__privateGet(this, _mediaStore)) {\n      (_b = __privateGet(this, _mediaStore)) == null ? void 0 : _b.dispatch({\n        type: \"documentelementchangerequest\",\n        detail: void 0\n      });\n      (_c = __privateGet(this, _mediaStore)) == null ? void 0 : _c.dispatch({\n        type: MediaUIEvents.MEDIA_TOGGLE_SUBTITLES_REQUEST,\n        detail: false\n      });\n    }\n    if (__privateGet(this, _mediaStoreUnsubscribe)) {\n      (_d = __privateGet(this, _mediaStoreUnsubscribe)) == null ? void 0 : _d.call(this);\n      __privateSet(this, _mediaStoreUnsubscribe, void 0);\n    }\n  }\n  /**\n   * @override\n   * @param {HTMLMediaElement} media\n   */\n  mediaSetCallback(media) {\n    var _a;\n    super.mediaSetCallback(media);\n    (_a = __privateGet(this, _mediaStore)) == null ? void 0 : _a.dispatch({\n      type: \"mediaelementchangerequest\",\n      detail: media\n    });\n    if (!media.hasAttribute(\"tabindex\")) {\n      media.tabIndex = -1;\n    }\n  }\n  /**\n   * @override\n   * @param {HTMLMediaElement} media\n   */\n  mediaUnsetCallback(media) {\n    var _a;\n    super.mediaUnsetCallback(media);\n    (_a = __privateGet(this, _mediaStore)) == null ? void 0 : _a.dispatch({\n      type: \"mediaelementchangerequest\",\n      detail: void 0\n    });\n  }\n  propagateMediaState(stateName, state) {\n    propagateMediaState(this.mediaStateReceivers, stateName, state);\n  }\n  associateElement(element) {\n    if (!element)\n      return;\n    const { associatedElementSubscriptions } = this;\n    if (associatedElementSubscriptions.has(element))\n      return;\n    const registerMediaStateReceiver = this.registerMediaStateReceiver.bind(this);\n    const unregisterMediaStateReceiver = this.unregisterMediaStateReceiver.bind(this);\n    const unsubscribe = monitorForMediaStateReceivers(\n      element,\n      registerMediaStateReceiver,\n      unregisterMediaStateReceiver\n    );\n    Object.values(MediaUIEvents).forEach((eventName) => {\n      element.addEventListener(eventName, __privateGet(this, _mediaStateEventHandler));\n    });\n    associatedElementSubscriptions.set(element, unsubscribe);\n  }\n  unassociateElement(element) {\n    if (!element)\n      return;\n    const { associatedElementSubscriptions } = this;\n    if (!associatedElementSubscriptions.has(element))\n      return;\n    const unsubscribe = associatedElementSubscriptions.get(element);\n    unsubscribe();\n    associatedElementSubscriptions.delete(element);\n    Object.values(MediaUIEvents).forEach((eventName) => {\n      element.removeEventListener(eventName, __privateGet(this, _mediaStateEventHandler));\n    });\n  }\n  registerMediaStateReceiver(el) {\n    if (!el)\n      return;\n    const els = this.mediaStateReceivers;\n    const index = els.indexOf(el);\n    if (index > -1)\n      return;\n    els.push(el);\n    if (__privateGet(this, _mediaStore)) {\n      Object.entries(__privateGet(this, _mediaStore).getState()).forEach(\n        ([stateName, stateValue]) => {\n          propagateMediaState([el], stateName, stateValue);\n        }\n      );\n    }\n  }\n  unregisterMediaStateReceiver(el) {\n    const els = this.mediaStateReceivers;\n    const index = els.indexOf(el);\n    if (index < 0)\n      return;\n    els.splice(index, 1);\n  }\n  enableHotkeys() {\n    this.addEventListener(\"keydown\", __privateMethod(this, _keyDownHandler, keyDownHandler_fn));\n  }\n  disableHotkeys() {\n    this.removeEventListener(\"keydown\", __privateMethod(this, _keyDownHandler, keyDownHandler_fn));\n    this.removeEventListener(\"keyup\", __privateMethod(this, _keyUpHandler, keyUpHandler_fn));\n  }\n  get hotkeys() {\n    return __privateGet(this, _hotKeys);\n  }\n  keyboardShortcutHandler(e) {\n    var _a, _b, _c, _d, _e;\n    const target = e.target;\n    const keysUsed = ((_c = (_b = (_a = target.getAttribute(Attributes.KEYS_USED)) == null ? void 0 : _a.split(\" \")) != null ? _b : target == null ? void 0 : target.keysUsed) != null ? _c : []).map((key) => key === \"Space\" ? \" \" : key).filter(Boolean);\n    if (keysUsed.includes(e.key)) {\n      return;\n    }\n    let eventName, detail, evt;\n    if (__privateGet(this, _hotKeys).contains(`no${e.key.toLowerCase()}`))\n      return;\n    if (e.key === \" \" && __privateGet(this, _hotKeys).contains(`nospace`))\n      return;\n    switch (e.key) {\n      case \" \":\n      case \"k\":\n        eventName = __privateGet(this, _mediaStore).getState().mediaPaused ? MediaUIEvents.MEDIA_PLAY_REQUEST : MediaUIEvents.MEDIA_PAUSE_REQUEST;\n        this.dispatchEvent(\n          new globalThis.CustomEvent(eventName, {\n            composed: true,\n            bubbles: true\n          })\n        );\n        break;\n      case \"m\":\n        eventName = this.mediaStore.getState().mediaVolumeLevel === \"off\" ? MediaUIEvents.MEDIA_UNMUTE_REQUEST : MediaUIEvents.MEDIA_MUTE_REQUEST;\n        this.dispatchEvent(\n          new globalThis.CustomEvent(eventName, {\n            composed: true,\n            bubbles: true\n          })\n        );\n        break;\n      case \"f\":\n        eventName = this.mediaStore.getState().mediaIsFullscreen ? MediaUIEvents.MEDIA_EXIT_FULLSCREEN_REQUEST : MediaUIEvents.MEDIA_ENTER_FULLSCREEN_REQUEST;\n        this.dispatchEvent(\n          new globalThis.CustomEvent(eventName, {\n            composed: true,\n            bubbles: true\n          })\n        );\n        break;\n      case \"c\":\n        this.dispatchEvent(\n          new globalThis.CustomEvent(\n            MediaUIEvents.MEDIA_TOGGLE_SUBTITLES_REQUEST,\n            { composed: true, bubbles: true }\n          )\n        );\n        break;\n      case \"ArrowLeft\": {\n        const offsetValue = this.hasAttribute(\n          Attributes.KEYBOARD_BACKWARD_SEEK_OFFSET\n        ) ? +this.getAttribute(Attributes.KEYBOARD_BACKWARD_SEEK_OFFSET) : DEFAULT_SEEK_OFFSET;\n        detail = Math.max(\n          ((_d = this.mediaStore.getState().mediaCurrentTime) != null ? _d : 0) - offsetValue,\n          0\n        );\n        evt = new globalThis.CustomEvent(MediaUIEvents.MEDIA_SEEK_REQUEST, {\n          composed: true,\n          bubbles: true,\n          detail\n        });\n        this.dispatchEvent(evt);\n        break;\n      }\n      case \"ArrowRight\": {\n        const offsetValue = this.hasAttribute(\n          Attributes.KEYBOARD_FORWARD_SEEK_OFFSET\n        ) ? +this.getAttribute(Attributes.KEYBOARD_FORWARD_SEEK_OFFSET) : DEFAULT_SEEK_OFFSET;\n        detail = Math.max(\n          ((_e = this.mediaStore.getState().mediaCurrentTime) != null ? _e : 0) + offsetValue,\n          0\n        );\n        evt = new globalThis.CustomEvent(MediaUIEvents.MEDIA_SEEK_REQUEST, {\n          composed: true,\n          bubbles: true,\n          detail\n        });\n        this.dispatchEvent(evt);\n        break;\n      }\n      default:\n        break;\n    }\n  }\n}\n_hotKeys = new WeakMap();\n_fullscreenElement = new WeakMap();\n_mediaStore = new WeakMap();\n_mediaStateCallback = new WeakMap();\n_mediaStoreUnsubscribe = new WeakMap();\n_mediaStateEventHandler = new WeakMap();\n_setupDefaultStore = new WeakSet();\nsetupDefaultStore_fn = function() {\n  var _a;\n  this.mediaStore = createMediaStore({\n    media: this.media,\n    fullscreenElement: this.fullscreenElement,\n    options: {\n      defaultSubtitles: this.hasAttribute(Attributes.DEFAULT_SUBTITLES),\n      defaultDuration: this.hasAttribute(Attributes.DEFAULT_DURATION) ? +this.getAttribute(Attributes.DEFAULT_DURATION) : void 0,\n      defaultStreamType: (\n        /** @type {import('./media-store/state-mediator.js').StreamTypeValue} */\n        (_a = this.getAttribute(\n          Attributes.DEFAULT_STREAM_TYPE\n        )) != null ? _a : void 0\n      ),\n      liveEdgeOffset: this.hasAttribute(Attributes.LIVE_EDGE_OFFSET) ? +this.getAttribute(Attributes.LIVE_EDGE_OFFSET) : void 0,\n      // NOTE: This wasn't updated if it was changed later. Should it be? (CJP)\n      noVolumePref: this.hasAttribute(Attributes.NO_VOLUME_PREF),\n      noSubtitlesLangPref: this.hasAttribute(\n        Attributes.NO_SUBTITLES_LANG_PREF\n      )\n    }\n  });\n};\n_keyUpHandler = new WeakSet();\nkeyUpHandler_fn = function(e) {\n  const { key } = e;\n  if (!ButtonPressedKeys.includes(key)) {\n    this.removeEventListener(\"keyup\", __privateMethod(this, _keyUpHandler, keyUpHandler_fn));\n    return;\n  }\n  this.keyboardShortcutHandler(e);\n};\n_keyDownHandler = new WeakSet();\nkeyDownHandler_fn = function(e) {\n  const { metaKey, altKey, key } = e;\n  if (metaKey || altKey || !ButtonPressedKeys.includes(key)) {\n    this.removeEventListener(\"keyup\", __privateMethod(this, _keyUpHandler, keyUpHandler_fn));\n    return;\n  }\n  if ([\" \", \"ArrowLeft\", \"ArrowRight\"].includes(key) && !(__privateGet(this, _hotKeys).contains(`no${key.toLowerCase()}`) || key === \" \" && __privateGet(this, _hotKeys).contains(\"nospace\"))) {\n    e.preventDefault();\n  }\n  this.addEventListener(\"keyup\", __privateMethod(this, _keyUpHandler, keyUpHandler_fn), { once: true });\n};\nconst MEDIA_UI_ATTRIBUTE_NAMES = Object.values(MediaUIAttributes);\nconst MEDIA_UI_PROP_NAMES = Object.values(MediaUIProps);\nconst getMediaUIAttributesFrom = (child) => {\n  var _a, _b, _c, _d;\n  let { observedAttributes } = child.constructor;\n  if (!observedAttributes && ((_a = child.nodeName) == null ? void 0 : _a.includes(\"-\"))) {\n    globalThis.customElements.upgrade(child);\n    ({ observedAttributes } = child.constructor);\n  }\n  const mediaChromeAttributesList = (_d = (_c = (_b = child == null ? void 0 : child.getAttribute) == null ? void 0 : _b.call(child, MediaStateReceiverAttributes.MEDIA_CHROME_ATTRIBUTES)) == null ? void 0 : _c.split) == null ? void 0 : _d.call(_c, /\\s+/);\n  if (!Array.isArray(observedAttributes || mediaChromeAttributesList))\n    return [];\n  return (observedAttributes || mediaChromeAttributesList).filter(\n    (attrName) => MEDIA_UI_ATTRIBUTE_NAMES.includes(attrName)\n  );\n};\nconst hasMediaUIProps = (mediaStateReceiverCandidate) => {\n  var _a, _b;\n  if (((_a = mediaStateReceiverCandidate.nodeName) == null ? void 0 : _a.includes(\"-\")) && !!globalThis.customElements.get(\n    (_b = mediaStateReceiverCandidate.nodeName) == null ? void 0 : _b.toLowerCase()\n  ) && !(mediaStateReceiverCandidate instanceof globalThis.customElements.get(\n    mediaStateReceiverCandidate.nodeName.toLowerCase()\n  ))) {\n    globalThis.customElements.upgrade(mediaStateReceiverCandidate);\n  }\n  return MEDIA_UI_PROP_NAMES.some(\n    (propName) => propName in mediaStateReceiverCandidate\n  );\n};\nconst isMediaStateReceiver = (child) => {\n  return hasMediaUIProps(child) || !!getMediaUIAttributesFrom(child).length;\n};\nconst serializeTuple = (tuple) => {\n  var _a;\n  return (_a = tuple == null ? void 0 : tuple.join) == null ? void 0 : _a.call(tuple, \":\");\n};\nconst CustomAttrSerializer = {\n  [MediaUIAttributes.MEDIA_SUBTITLES_LIST]: stringifyTextTrackList,\n  [MediaUIAttributes.MEDIA_SUBTITLES_SHOWING]: stringifyTextTrackList,\n  [MediaUIAttributes.MEDIA_SEEKABLE]: serializeTuple,\n  [MediaUIAttributes.MEDIA_BUFFERED]: (tuples) => tuples == null ? void 0 : tuples.map(serializeTuple).join(\" \"),\n  [MediaUIAttributes.MEDIA_PREVIEW_COORDS]: (coords) => coords == null ? void 0 : coords.join(\" \"),\n  [MediaUIAttributes.MEDIA_RENDITION_LIST]: stringifyRenditionList,\n  [MediaUIAttributes.MEDIA_AUDIO_TRACK_LIST]: stringifyAudioTrackList\n};\nconst setAttr = async (child, attrName, attrValue) => {\n  var _a, _b;\n  if (!child.isConnected) {\n    await delay(0);\n  }\n  if (typeof attrValue === \"boolean\" || attrValue == null) {\n    return setBooleanAttr(child, attrName, attrValue);\n  }\n  if (typeof attrValue === \"number\") {\n    return setNumericAttr(child, attrName, attrValue);\n  }\n  if (typeof attrValue === \"string\") {\n    return setStringAttr(child, attrName, attrValue);\n  }\n  if (Array.isArray(attrValue) && !attrValue.length) {\n    return child.removeAttribute(attrName);\n  }\n  const val = (_b = (_a = CustomAttrSerializer[attrName]) == null ? void 0 : _a.call(CustomAttrSerializer, attrValue)) != null ? _b : attrValue;\n  return child.setAttribute(attrName, val);\n};\nconst isMediaSlotElementDescendant = (el) => {\n  var _a;\n  return !!((_a = el.closest) == null ? void 0 : _a.call(el, '*[slot=\"media\"]'));\n};\nconst traverseForMediaStateReceivers = (rootNode, mediaStateReceiverCallback) => {\n  if (isMediaSlotElementDescendant(rootNode)) {\n    return;\n  }\n  const traverseForMediaStateReceiversSync = (rootNode2, mediaStateReceiverCallback2) => {\n    var _a, _b;\n    if (isMediaStateReceiver(rootNode2)) {\n      mediaStateReceiverCallback2(rootNode2);\n    }\n    const { children = [] } = rootNode2 != null ? rootNode2 : {};\n    const shadowChildren = (_b = (_a = rootNode2 == null ? void 0 : rootNode2.shadowRoot) == null ? void 0 : _a.children) != null ? _b : [];\n    const allChildren = [...children, ...shadowChildren];\n    allChildren.forEach(\n      (child) => traverseForMediaStateReceivers(\n        child,\n        mediaStateReceiverCallback2\n      )\n    );\n  };\n  const name = rootNode == null ? void 0 : rootNode.nodeName.toLowerCase();\n  if (name.includes(\"-\") && !isMediaStateReceiver(rootNode)) {\n    globalThis.customElements.whenDefined(name).then(() => {\n      traverseForMediaStateReceiversSync(rootNode, mediaStateReceiverCallback);\n    });\n    return;\n  }\n  traverseForMediaStateReceiversSync(rootNode, mediaStateReceiverCallback);\n};\nconst propagateMediaState = (els, stateName, val) => {\n  els.forEach((el) => {\n    if (stateName in el) {\n      el[stateName] = val;\n      return;\n    }\n    const relevantAttrs = getMediaUIAttributesFrom(el);\n    const attrName = stateName.toLowerCase();\n    if (!relevantAttrs.includes(attrName))\n      return;\n    setAttr(el, attrName, val);\n  });\n};\nconst monitorForMediaStateReceivers = (rootNode, registerMediaStateReceiver, unregisterMediaStateReceiver) => {\n  traverseForMediaStateReceivers(rootNode, registerMediaStateReceiver);\n  const registerMediaStateReceiverHandler = (evt) => {\n    var _a;\n    const el = (_a = evt == null ? void 0 : evt.composedPath()[0]) != null ? _a : evt.target;\n    registerMediaStateReceiver(el);\n  };\n  const unregisterMediaStateReceiverHandler = (evt) => {\n    var _a;\n    const el = (_a = evt == null ? void 0 : evt.composedPath()[0]) != null ? _a : evt.target;\n    unregisterMediaStateReceiver(el);\n  };\n  rootNode.addEventListener(\n    MediaUIEvents.REGISTER_MEDIA_STATE_RECEIVER,\n    registerMediaStateReceiverHandler\n  );\n  rootNode.addEventListener(\n    MediaUIEvents.UNREGISTER_MEDIA_STATE_RECEIVER,\n    unregisterMediaStateReceiverHandler\n  );\n  const mutationCallback = (mutationsList) => {\n    mutationsList.forEach((mutationRecord) => {\n      const {\n        addedNodes = [],\n        removedNodes = [],\n        type,\n        target,\n        attributeName\n      } = mutationRecord;\n      if (type === \"childList\") {\n        Array.prototype.forEach.call(\n          addedNodes,\n          (node) => traverseForMediaStateReceivers(\n            node,\n            registerMediaStateReceiver\n          )\n        );\n        Array.prototype.forEach.call(\n          removedNodes,\n          (node) => traverseForMediaStateReceivers(\n            node,\n            unregisterMediaStateReceiver\n          )\n        );\n      } else if (type === \"attributes\" && attributeName === MediaStateReceiverAttributes.MEDIA_CHROME_ATTRIBUTES) {\n        if (isMediaStateReceiver(target)) {\n          registerMediaStateReceiver(target);\n        } else {\n          unregisterMediaStateReceiver(target);\n        }\n      }\n    });\n  };\n  let prevSlotted = [];\n  const slotChangeHandler = (event) => {\n    const slotEl = event.target;\n    if (slotEl.name === \"media\")\n      return;\n    prevSlotted.forEach(\n      (node) => traverseForMediaStateReceivers(node, unregisterMediaStateReceiver)\n    );\n    prevSlotted = [\n      ...slotEl.assignedElements({ flatten: true })\n    ];\n    prevSlotted.forEach(\n      (node) => traverseForMediaStateReceivers(node, registerMediaStateReceiver)\n    );\n  };\n  rootNode.addEventListener(\"slotchange\", slotChangeHandler);\n  const observer = new MutationObserver(mutationCallback);\n  observer.observe(rootNode, {\n    childList: true,\n    attributes: true,\n    subtree: true\n  });\n  const unsubscribe = () => {\n    traverseForMediaStateReceivers(rootNode, unregisterMediaStateReceiver);\n    rootNode.removeEventListener(\"slotchange\", slotChangeHandler);\n    observer.disconnect();\n    rootNode.removeEventListener(\n      MediaUIEvents.REGISTER_MEDIA_STATE_RECEIVER,\n      registerMediaStateReceiverHandler\n    );\n    rootNode.removeEventListener(\n      MediaUIEvents.UNREGISTER_MEDIA_STATE_RECEIVER,\n      unregisterMediaStateReceiverHandler\n    );\n  };\n  return unsubscribe;\n};\nif (!globalThis.customElements.get(\"media-controller\")) {\n  globalThis.customElements.define(\"media-controller\", MediaController);\n}\nvar media_controller_default = MediaController;\nexport {\n  Attributes,\n  MediaController,\n  media_controller_default as default\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar __privateSet = (obj, member, value, setter) => {\n  __accessCheck(obj, member, \"write to private field\");\n  setter ? setter.call(obj, value) : member.set(obj, value);\n  return value;\n};\nvar __privateMethod = (obj, member, method) => {\n  __accessCheck(obj, member, \"access private method\");\n  return method;\n};\nvar _mediaController, _clickListener, _positionTooltip, _keyupListener, _keydownListener, _setupTooltip, setupTooltip_fn;\nimport { MediaStateReceiverAttributes } from \"./constants.js\";\nimport {\n  getOrInsertCSSRule,\n  getStringAttr,\n  setStringAttr\n} from \"./utils/element-utils.js\";\nimport { globalThis, document } from \"./utils/server-safe-globals.js\";\nconst Attributes = {\n  TOOLTIP_PLACEMENT: \"tooltipplacement\"\n};\nconst template = document.createElement(\"template\");\ntemplate.innerHTML = /*html*/\n`\n<style>\n  :host {\n    position: relative;\n    font: var(--media-font,\n      var(--media-font-weight, bold)\n      var(--media-font-size, 14px) /\n      var(--media-text-content-height, var(--media-control-height, 24px))\n      var(--media-font-family, helvetica neue, segoe ui, roboto, arial, sans-serif));\n    color: var(--media-text-color, var(--media-primary-color, rgb(238 238 238)));\n    background: var(--media-control-background, var(--media-secondary-color, rgb(20 20 30 / .7)));\n    padding: var(--media-button-padding, var(--media-control-padding, 10px));\n    justify-content: var(--media-button-justify-content, center);\n    display: inline-flex;\n    align-items: center;\n    vertical-align: middle;\n    box-sizing: border-box;\n    transition: background .15s linear;\n    pointer-events: auto;\n    cursor: pointer;\n    -webkit-tap-highlight-color: transparent;\n  }\n\n  ${/*\n  Only show outline when keyboard focusing.\n  https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo\n*/\n\"\"}\n  :host(:focus-visible) {\n    box-shadow: inset 0 0 0 2px rgb(27 127 204 / .9);\n    outline: 0;\n  }\n  ${/*\n * hide default focus ring, particularly when using mouse\n */\n\"\"}\n  :host(:where(:focus)) {\n    box-shadow: none;\n    outline: 0;\n  }\n\n  :host(:hover) {\n    background: var(--media-control-hover-background, rgba(50 50 70 / .7));\n  }\n\n  svg, img, ::slotted(svg), ::slotted(img) {\n    width: var(--media-button-icon-width);\n    height: var(--media-button-icon-height, var(--media-control-height, 24px));\n    transform: var(--media-button-icon-transform);\n    transition: var(--media-button-icon-transition);\n    fill: var(--media-icon-color, var(--media-primary-color, rgb(238 238 238)));\n    vertical-align: middle;\n    max-width: 100%;\n    max-height: 100%;\n    min-width: 100%;\n  }\n\n  media-tooltip {\n    ${/** Make sure unpositioned tooltip doesn't cause page overflow (scroll). */\n\"\"}\n    max-width: 0;\n    overflow-x: clip;\n    opacity: 0;\n    transition: opacity .3s, max-width 0s 9s;\n  }\n\n  :host(:hover) media-tooltip,\n  :host(:focus-visible) media-tooltip {\n    max-width: 100vw;\n    opacity: 1;\n    transition: opacity .3s;\n  }\n\n  :host([notooltip]) slot[name=\"tooltip\"] {\n    display: none;\n  }\n</style>\n\n<slot name=\"tooltip\">\n  <media-tooltip part=\"tooltip\" aria-hidden=\"true\">\n    <slot name=\"tooltip-content\"></slot>\n  </media-tooltip>\n</slot>\n`;\nclass MediaChromeButton extends globalThis.HTMLElement {\n  constructor(options = {}) {\n    var _a;\n    super();\n    // Called when we know the tooltip is ready / defined\n    __privateAdd(this, _setupTooltip);\n    __privateAdd(this, _mediaController, void 0);\n    this.preventClick = false;\n    this.tooltipEl = null;\n    this.tooltipContent = \"\";\n    __privateAdd(this, _clickListener, (e) => {\n      if (!this.preventClick) {\n        this.handleClick(e);\n      }\n      setTimeout(__privateGet(this, _positionTooltip), 0);\n    });\n    __privateAdd(this, _positionTooltip, () => {\n      var _a, _b;\n      (_b = (_a = this.tooltipEl) == null ? void 0 : _a.updateXOffset) == null ? void 0 : _b.call(_a);\n    });\n    // NOTE: There are definitely some \"false positive\" cases with multi-key pressing,\n    // but this should be good enough for most use cases.\n    __privateAdd(this, _keyupListener, (e) => {\n      const { key } = e;\n      if (!this.keysUsed.includes(key)) {\n        this.removeEventListener(\"keyup\", __privateGet(this, _keyupListener));\n        return;\n      }\n      if (!this.preventClick) {\n        this.handleClick(e);\n      }\n    });\n    __privateAdd(this, _keydownListener, (e) => {\n      const { metaKey, altKey, key } = e;\n      if (metaKey || altKey || !this.keysUsed.includes(key)) {\n        this.removeEventListener(\"keyup\", __privateGet(this, _keyupListener));\n        return;\n      }\n      this.addEventListener(\"keyup\", __privateGet(this, _keyupListener), { once: true });\n    });\n    if (!this.shadowRoot) {\n      this.attachShadow({ mode: \"open\" });\n      const buttonHTML = template.content.cloneNode(true);\n      this.nativeEl = buttonHTML;\n      let slotTemplate = options.slotTemplate;\n      if (!slotTemplate) {\n        slotTemplate = document.createElement(\"template\");\n        slotTemplate.innerHTML = `<slot>${options.defaultContent || \"\"}</slot>`;\n      }\n      if (options.tooltipContent) {\n        buttonHTML.querySelector('slot[name=\"tooltip-content\"]').innerHTML = (_a = options.tooltipContent) != null ? _a : \"\";\n        this.tooltipContent = options.tooltipContent;\n      }\n      this.nativeEl.appendChild(slotTemplate.content.cloneNode(true));\n      this.shadowRoot.appendChild(buttonHTML);\n    }\n    this.tooltipEl = this.shadowRoot.querySelector(\"media-tooltip\");\n  }\n  static get observedAttributes() {\n    return [\n      \"disabled\",\n      Attributes.TOOLTIP_PLACEMENT,\n      MediaStateReceiverAttributes.MEDIA_CONTROLLER\n    ];\n  }\n  enable() {\n    this.addEventListener(\"click\", __privateGet(this, _clickListener));\n    this.addEventListener(\"keydown\", __privateGet(this, _keydownListener));\n    this.tabIndex = 0;\n  }\n  disable() {\n    this.removeEventListener(\"click\", __privateGet(this, _clickListener));\n    this.removeEventListener(\"keydown\", __privateGet(this, _keydownListener));\n    this.removeEventListener(\"keyup\", __privateGet(this, _keyupListener));\n    this.tabIndex = -1;\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    var _a, _b, _c, _d, _e;\n    if (attrName === MediaStateReceiverAttributes.MEDIA_CONTROLLER) {\n      if (oldValue) {\n        (_b = (_a = __privateGet(this, _mediaController)) == null ? void 0 : _a.unassociateElement) == null ? void 0 : _b.call(_a, this);\n        __privateSet(this, _mediaController, null);\n      }\n      if (newValue && this.isConnected) {\n        __privateSet(this, _mediaController, (_c = this.getRootNode()) == null ? void 0 : _c.getElementById(newValue));\n        (_e = (_d = __privateGet(this, _mediaController)) == null ? void 0 : _d.associateElement) == null ? void 0 : _e.call(_d, this);\n      }\n    } else if (attrName === \"disabled\" && newValue !== oldValue) {\n      if (newValue == null) {\n        this.enable();\n      } else {\n        this.disable();\n      }\n    } else if (attrName === Attributes.TOOLTIP_PLACEMENT && this.tooltipEl && newValue !== oldValue) {\n      this.tooltipEl.placement = newValue;\n    }\n    __privateGet(this, _positionTooltip).call(this);\n  }\n  connectedCallback() {\n    var _a, _b, _c;\n    const { style } = getOrInsertCSSRule(this.shadowRoot, \":host\");\n    style.setProperty(\n      \"display\",\n      `var(--media-control-display, var(--${this.localName}-display, inline-flex))`\n    );\n    if (!this.hasAttribute(\"disabled\")) {\n      this.enable();\n    }\n    this.setAttribute(\"role\", \"button\");\n    const mediaControllerId = this.getAttribute(\n      MediaStateReceiverAttributes.MEDIA_CONTROLLER\n    );\n    if (mediaControllerId) {\n      __privateSet(\n        this,\n        _mediaController,\n        // @ts-ignore\n        (_a = this.getRootNode()) == null ? void 0 : _a.getElementById(mediaControllerId)\n      );\n      (_c = (_b = __privateGet(this, _mediaController)) == null ? void 0 : _b.associateElement) == null ? void 0 : _c.call(_b, this);\n    }\n    globalThis.customElements.whenDefined(\"media-tooltip\").then(() => __privateMethod(this, _setupTooltip, setupTooltip_fn).call(this));\n  }\n  disconnectedCallback() {\n    var _a, _b;\n    this.disable();\n    (_b = (_a = __privateGet(this, _mediaController)) == null ? void 0 : _a.unassociateElement) == null ? void 0 : _b.call(_a, this);\n    __privateSet(this, _mediaController, null);\n    this.removeEventListener(\"mouseenter\", __privateGet(this, _positionTooltip));\n    this.removeEventListener(\"focus\", __privateGet(this, _positionTooltip));\n    this.removeEventListener(\"click\", __privateGet(this, _clickListener));\n  }\n  get keysUsed() {\n    return [\"Enter\", \" \"];\n  }\n  /**\n   * Get or set tooltip placement\n   */\n  get tooltipPlacement() {\n    return getStringAttr(this, Attributes.TOOLTIP_PLACEMENT);\n  }\n  set tooltipPlacement(value) {\n    setStringAttr(this, Attributes.TOOLTIP_PLACEMENT, value);\n  }\n  /**\n   * @abstract\n   * @argument {Event} e\n   */\n  handleClick(e) {\n  }\n  // eslint-disable-line\n}\n_mediaController = new WeakMap();\n_clickListener = new WeakMap();\n_positionTooltip = new WeakMap();\n_keyupListener = new WeakMap();\n_keydownListener = new WeakMap();\n_setupTooltip = new WeakSet();\nsetupTooltip_fn = function() {\n  this.addEventListener(\"mouseenter\", __privateGet(this, _positionTooltip));\n  this.addEventListener(\"focus\", __privateGet(this, _positionTooltip));\n  this.addEventListener(\"click\", __privateGet(this, _clickListener));\n  const initialPlacement = this.tooltipPlacement;\n  if (initialPlacement && this.tooltipEl) {\n    this.tooltipEl.placement = initialPlacement;\n  }\n};\nif (!globalThis.customElements.get(\"media-chrome-button\")) {\n  globalThis.customElements.define(\"media-chrome-button\", MediaChromeButton);\n}\nvar media_chrome_button_default = MediaChromeButton;\nexport {\n  MediaChromeButton,\n  media_chrome_button_default as default\n};\n", "import { MediaChromeButton } from \"./media-chrome-button.js\";\nimport { globalThis, document } from \"./utils/server-safe-globals.js\";\nimport { MediaUIEvents, MediaUIAttributes } from \"./constants.js\";\nimport { tooltipLabels, verbs } from \"./labels/labels.js\";\nimport {\n  getStringAttr,\n  setStringAttr,\n  getBooleanAttr,\n  setBooleanAttr\n} from \"./utils/element-utils.js\";\nconst airplayIcon = `<svg aria-hidden=\"true\" viewBox=\"0 0 26 24\">\n  <path d=\"M22.13 3H3.87a.87.87 0 0 0-.87.87v13.26a.87.87 0 0 0 .87.87h3.4L9 16H5V5h16v11h-4l1.72 2h3.4a.87.87 0 0 0 .87-.87V3.87a.87.87 0 0 0-.86-.87Zm-8.75 11.44a.5.5 0 0 0-.76 0l-4.91 5.73a.5.5 0 0 0 .38.83h9.82a.501.501 0 0 0 .38-.83l-4.91-5.73Z\"/>\n</svg>\n`;\nconst slotTemplate = document.createElement(\"template\");\nslotTemplate.innerHTML = /*html*/\n`\n  <style>\n    :host([${MediaUIAttributes.MEDIA_IS_AIRPLAYING}]) slot[name=icon] slot:not([name=exit]) {\n      display: none !important;\n    }\n\n    ${/* Double negative, but safer if display doesn't equal 'block' */\n\"\"}\n    :host(:not([${MediaUIAttributes.MEDIA_IS_AIRPLAYING}])) slot[name=icon] slot:not([name=enter]) {\n      display: none !important;\n    }\n\n    :host([${MediaUIAttributes.MEDIA_IS_AIRPLAYING}]) slot[name=tooltip-enter],\n    :host(:not([${MediaUIAttributes.MEDIA_IS_AIRPLAYING}])) slot[name=tooltip-exit] {\n      display: none;\n    }\n  </style>\n\n  <slot name=\"icon\">\n    <slot name=\"enter\">${airplayIcon}</slot>\n    <slot name=\"exit\">${airplayIcon}</slot>\n  </slot>\n`;\nconst tooltipContent = (\n  /*html*/\n  `\n  <slot name=\"tooltip-enter\">${tooltipLabels.ENTER_AIRPLAY}</slot>\n  <slot name=\"tooltip-exit\">${tooltipLabels.EXIT_AIRPLAY}</slot>\n`\n);\nconst updateAriaLabel = (el) => {\n  const label = el.mediaIsAirplaying ? verbs.EXIT_AIRPLAY() : verbs.ENTER_AIRPLAY();\n  el.setAttribute(\"aria-label\", label);\n};\nclass MediaAirplayButton extends MediaChromeButton {\n  static get observedAttributes() {\n    return [\n      ...super.observedAttributes,\n      MediaUIAttributes.MEDIA_IS_AIRPLAYING,\n      MediaUIAttributes.MEDIA_AIRPLAY_UNAVAILABLE\n    ];\n  }\n  constructor(options = {}) {\n    super({ slotTemplate, tooltipContent, ...options });\n  }\n  connectedCallback() {\n    super.connectedCallback();\n    updateAriaLabel(this);\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    super.attributeChangedCallback(attrName, oldValue, newValue);\n    if (attrName === MediaUIAttributes.MEDIA_IS_AIRPLAYING) {\n      updateAriaLabel(this);\n    }\n  }\n  /**\n   * Are we currently airplaying\n   */\n  get mediaIsAirplaying() {\n    return getBooleanAttr(this, MediaUIAttributes.MEDIA_IS_AIRPLAYING);\n  }\n  set mediaIsAirplaying(value) {\n    setBooleanAttr(this, MediaUIAttributes.MEDIA_IS_AIRPLAYING, value);\n  }\n  /**\n   * Airplay unavailability state\n   */\n  get mediaAirplayUnavailable() {\n    return getStringAttr(this, MediaUIAttributes.MEDIA_AIRPLAY_UNAVAILABLE);\n  }\n  set mediaAirplayUnavailable(value) {\n    setStringAttr(this, MediaUIAttributes.MEDIA_AIRPLAY_UNAVAILABLE, value);\n  }\n  handleClick() {\n    const evt = new globalThis.CustomEvent(\n      MediaUIEvents.MEDIA_AIRPLAY_REQUEST,\n      {\n        composed: true,\n        bubbles: true\n      }\n    );\n    this.dispatchEvent(evt);\n  }\n}\nif (!globalThis.customElements.get(\"media-airplay-button\")) {\n  globalThis.customElements.define(\"media-airplay-button\", MediaAirplayButton);\n}\nvar media_airplay_button_default = MediaAirplayButton;\nexport {\n  media_airplay_button_default as default\n};\n", "import { MediaChromeButton } from \"./media-chrome-button.js\";\nimport { globalThis, document } from \"./utils/server-safe-globals.js\";\nimport { MediaUIAttributes, MediaUIEvents } from \"./constants.js\";\nimport { nouns, tooltipLabels } from \"./labels/labels.js\";\nimport {\n  areSubsOn,\n  parseTextTracksStr,\n  stringifyTextTrackList\n} from \"./utils/captions.js\";\nconst ccIconOn = `<svg aria-hidden=\"true\" viewBox=\"0 0 26 24\">\n  <path d=\"M22.83 5.68a2.58 2.58 0 0 0-2.3-2.5c-3.62-.24-11.44-.24-15.06 0a2.58 2.58 0 0 0-2.3 2.5c-.23 4.21-.23 8.43 0 12.64a2.58 2.58 0 0 0 2.3 2.5c3.62.24 11.44.24 15.06 0a2.58 2.58 0 0 0 2.3-2.5c.23-4.21.23-8.43 0-12.64Zm-11.39 9.45a3.07 3.07 0 0 1-1.91.57 3.06 3.06 0 0 1-2.34-1 3.75 3.75 0 0 1-.92-2.67 3.92 3.92 0 0 1 .92-2.77 3.18 3.18 0 0 1 2.43-1 2.94 2.94 0 0 1 2.13.78c.364.359.62.813.74 1.31l-1.43.35a1.49 1.49 0 0 0-1.51-1.17 1.61 1.61 0 0 0-1.29.58 2.79 2.79 0 0 0-.5 1.89 3 3 0 0 0 .49 1.93 1.61 1.61 0 0 0 1.27.58 1.48 1.48 0 0 0 1-.37 2.1 2.1 0 0 0 .59-1.14l1.4.44a3.23 3.23 0 0 1-1.07 1.69Zm7.22 0a3.07 3.07 0 0 1-1.91.57 3.06 3.06 0 0 1-2.34-1 3.75 3.75 0 0 1-.92-2.67 3.88 3.88 0 0 1 .93-2.77 3.14 3.14 0 0 1 2.42-1 3 3 0 0 1 2.16.82 2.8 2.8 0 0 1 .73 1.31l-1.43.35a1.49 1.49 0 0 0-1.51-1.21 1.61 1.61 0 0 0-1.29.58A2.79 2.79 0 0 0 15 12a3 3 0 0 0 .49 1.93 1.61 1.61 0 0 0 1.27.58 1.44 1.44 0 0 0 1-.37 2.1 2.1 0 0 0 .6-1.15l1.4.44a3.17 3.17 0 0 1-1.1 1.7Z\"/>\n</svg>`;\nconst ccIconOff = `<svg aria-hidden=\"true\" viewBox=\"0 0 26 24\">\n  <path d=\"M17.73 14.09a1.4 1.4 0 0 1-1 .37 1.579 1.579 0 0 1-1.27-.58A3 3 0 0 1 15 12a2.8 2.8 0 0 1 .5-1.85 1.63 1.63 0 0 1 1.29-.57 1.47 1.47 0 0 1 1.51 1.2l1.43-.34A2.89 2.89 0 0 0 19 9.07a3 3 0 0 0-2.14-.78 3.14 3.14 0 0 0-2.42 1 3.91 3.91 0 0 0-.93 2.78 3.74 3.74 0 0 0 .92 2.66 3.07 3.07 0 0 0 2.34 1 3.07 3.07 0 0 0 1.91-.57 3.17 3.17 0 0 0 1.07-1.74l-1.4-.45c-.083.43-.3.822-.62 1.12Zm-7.22 0a1.43 1.43 0 0 1-1 .37 1.58 1.58 0 0 1-1.27-.58A3 3 0 0 1 7.76 12a2.8 2.8 0 0 1 .5-1.85 1.63 1.63 0 0 1 1.29-.57 1.47 1.47 0 0 1 1.51 1.2l1.43-.34a2.81 2.81 0 0 0-.74-1.32 2.94 2.94 0 0 0-2.13-.78 3.18 3.18 0 0 0-2.43 1 4 4 0 0 0-.92 2.78 3.74 3.74 0 0 0 .92 2.66 3.07 3.07 0 0 0 2.34 1 3.07 3.07 0 0 0 1.91-.57 3.23 3.23 0 0 0 1.07-1.74l-1.4-.45a2.06 2.06 0 0 1-.6 1.07Zm12.32-8.41a2.59 2.59 0 0 0-2.3-2.51C18.72 3.05 15.86 3 13 3c-2.86 0-5.72.05-7.53.17a2.59 2.59 0 0 0-2.3 2.51c-.23 4.207-.23 8.423 0 12.63a2.57 2.57 0 0 0 2.3 2.5c1.81.13 4.67.19 7.53.19 2.86 0 5.72-.06 7.53-.19a2.57 2.57 0 0 0 2.3-2.5c.23-4.207.23-8.423 0-12.63Zm-1.49 12.53a1.11 1.11 0 0 1-.91 1.11c-1.67.11-4.45.18-7.43.18-2.98 0-5.76-.07-7.43-.18a1.11 1.11 0 0 1-.91-1.11c-.21-4.14-.21-8.29 0-12.43a1.11 1.11 0 0 1 .91-1.11C7.24 4.56 10 4.49 13 4.49s5.76.07 7.43.18a1.11 1.11 0 0 1 .91 1.11c.21 4.14.21 8.29 0 12.43Z\"/>\n</svg>`;\nconst slotTemplate = document.createElement(\"template\");\nslotTemplate.innerHTML = /*html*/\n`\n  <style>\n    :host([aria-checked=\"true\"]) slot[name=off] {\n      display: none !important;\n    }\n\n    ${/* Double negative, but safer if display doesn't equal 'block' */\n\"\"}\n    :host(:not([aria-checked=\"true\"])) slot[name=on] {\n      display: none !important;\n    }\n\n    :host([aria-checked=\"true\"]) slot[name=tooltip-enable],\n    :host(:not([aria-checked=\"true\"])) slot[name=tooltip-disable] {\n      display: none;\n    }\n  </style>\n\n  <slot name=\"icon\">\n    <slot name=\"on\">${ccIconOn}</slot>\n    <slot name=\"off\">${ccIconOff}</slot>\n  </slot>\n`;\nconst tooltipContent = (\n  /*html*/\n  `\n  <slot name=\"tooltip-enable\">${tooltipLabels.ENABLE_CAPTIONS}</slot>\n  <slot name=\"tooltip-disable\">${tooltipLabels.DISABLE_CAPTIONS}</slot>\n`\n);\nconst updateAriaChecked = (el) => {\n  el.setAttribute(\"aria-checked\", areSubsOn(el).toString());\n};\nclass MediaCaptionsButton extends MediaChromeButton {\n  static get observedAttributes() {\n    return [\n      ...super.observedAttributes,\n      MediaUIAttributes.MEDIA_SUBTITLES_LIST,\n      MediaUIAttributes.MEDIA_SUBTITLES_SHOWING\n    ];\n  }\n  constructor(options = {}) {\n    super({ slotTemplate, tooltipContent, ...options });\n    this._captionsReady = false;\n  }\n  connectedCallback() {\n    super.connectedCallback();\n    this.setAttribute(\"role\", \"switch\");\n    this.setAttribute(\"aria-label\", nouns.CLOSED_CAPTIONS());\n    updateAriaChecked(this);\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    super.attributeChangedCallback(attrName, oldValue, newValue);\n    if (attrName === MediaUIAttributes.MEDIA_SUBTITLES_SHOWING) {\n      updateAriaChecked(this);\n    }\n  }\n  /**\n   * An array of TextTrack-like objects.\n   * Objects must have the properties: kind, language, and label.\n   */\n  get mediaSubtitlesList() {\n    return getSubtitlesListAttr(this, MediaUIAttributes.MEDIA_SUBTITLES_LIST);\n  }\n  set mediaSubtitlesList(list) {\n    setSubtitlesListAttr(this, MediaUIAttributes.MEDIA_SUBTITLES_LIST, list);\n  }\n  /**\n   * An array of TextTrack-like objects.\n   * Objects must have the properties: kind, language, and label.\n   */\n  get mediaSubtitlesShowing() {\n    return getSubtitlesListAttr(\n      this,\n      MediaUIAttributes.MEDIA_SUBTITLES_SHOWING\n    );\n  }\n  set mediaSubtitlesShowing(list) {\n    setSubtitlesListAttr(this, MediaUIAttributes.MEDIA_SUBTITLES_SHOWING, list);\n  }\n  handleClick() {\n    this.dispatchEvent(\n      new globalThis.CustomEvent(MediaUIEvents.MEDIA_TOGGLE_SUBTITLES_REQUEST, {\n        composed: true,\n        bubbles: true\n      })\n    );\n  }\n}\nconst getSubtitlesListAttr = (el, attrName) => {\n  const attrVal = el.getAttribute(attrName);\n  return attrVal ? parseTextTracksStr(attrVal) : [];\n};\nconst setSubtitlesListAttr = (el, attrName, list) => {\n  if (!(list == null ? void 0 : list.length)) {\n    el.removeAttribute(attrName);\n    return;\n  }\n  const newValStr = stringifyTextTrackList(list);\n  const oldVal = el.getAttribute(attrName);\n  if (oldVal === newValStr)\n    return;\n  el.setAttribute(attrName, newValStr);\n};\nif (!globalThis.customElements.get(\"media-captions-button\")) {\n  globalThis.customElements.define(\n    \"media-captions-button\",\n    MediaCaptionsButton\n  );\n}\nvar media_captions_button_default = MediaCaptionsButton;\nexport {\n  MediaCaptionsButton,\n  media_captions_button_default as default\n};\n", "import { MediaChromeButton } from \"./media-chrome-button.js\";\nimport { globalThis, document } from \"./utils/server-safe-globals.js\";\nimport { MediaUIEvents, MediaUIAttributes } from \"./constants.js\";\nimport { tooltipLabels, verbs } from \"./labels/labels.js\";\nimport {\n  getBooleanAttr,\n  setBooleanAttr,\n  getStringAttr,\n  setStringAttr\n} from \"./utils/element-utils.js\";\nconst enterIcon = `<svg aria-hidden=\"true\" viewBox=\"0 0 24 24\"><g><path class=\"cast_caf_icon_arch0\" d=\"M1,18 L1,21 L4,21 C4,19.3 2.66,18 1,18 L1,18 Z\"/><path class=\"cast_caf_icon_arch1\" d=\"M1,14 L1,16 C3.76,16 6,18.2 6,21 L8,21 C8,17.13 4.87,14 1,14 L1,14 Z\"/><path class=\"cast_caf_icon_arch2\" d=\"M1,10 L1,12 C5.97,12 10,16.0 10,21 L12,21 C12,14.92 7.07,10 1,10 L1,10 Z\"/><path class=\"cast_caf_icon_box\" d=\"M21,3 L3,3 C1.9,3 1,3.9 1,5 L1,8 L3,8 L3,5 L21,5 L21,19 L14,19 L14,21 L21,21 C22.1,21 23,20.1 23,19 L23,5 C23,3.9 22.1,3 21,3 L21,3 Z\"/></g></svg>`;\nconst exitIcon = `<svg aria-hidden=\"true\" viewBox=\"0 0 24 24\"><g><path class=\"cast_caf_icon_arch0\" d=\"M1,18 L1,21 L4,21 C4,19.3 2.66,18 1,18 L1,18 Z\"/><path class=\"cast_caf_icon_arch1\" d=\"M1,14 L1,16 C3.76,16 6,18.2 6,21 L8,21 C8,17.13 4.87,14 1,14 L1,14 Z\"/><path class=\"cast_caf_icon_arch2\" d=\"M1,10 L1,12 C5.97,12 10,16.0 10,21 L12,21 C12,14.92 7.07,10 1,10 L1,10 Z\"/><path class=\"cast_caf_icon_box\" d=\"M21,3 L3,3 C1.9,3 1,3.9 1,5 L1,8 L3,8 L3,5 L21,5 L21,19 L14,19 L14,21 L21,21 C22.1,21 23,20.1 23,19 L23,5 C23,3.9 22.1,3 21,3 L21,3 Z\"/><path class=\"cast_caf_icon_boxfill\" d=\"M5,7 L5,8.63 C8,8.6 13.37,14 13.37,17 L19,17 L19,7 Z\"/></g></svg>`;\nconst slotTemplate = document.createElement(\"template\");\nslotTemplate.innerHTML = /*html*/\n`\n  <style>\n  :host([${MediaUIAttributes.MEDIA_IS_CASTING}]) slot[name=icon] slot:not([name=exit]) {\n    display: none !important;\n  }\n\n  ${/* Double negative, but safer if display doesn't equal 'block' */\n\"\"}\n  :host(:not([${MediaUIAttributes.MEDIA_IS_CASTING}])) slot[name=icon] slot:not([name=enter]) {\n    display: none !important;\n  }\n\n  :host([${MediaUIAttributes.MEDIA_IS_CASTING}]) slot[name=tooltip-enter],\n    :host(:not([${MediaUIAttributes.MEDIA_IS_CASTING}])) slot[name=tooltip-exit] {\n      display: none;\n    }\n  </style>\n\n  <slot name=\"icon\">\n    <slot name=\"enter\">${enterIcon}</slot>\n    <slot name=\"exit\">${exitIcon}</slot>\n  </slot>\n`;\nconst tooltipContent = (\n  /*html*/\n  `\n  <slot name=\"tooltip-enter\">${tooltipLabels.START_CAST}</slot>\n  <slot name=\"tooltip-exit\">${tooltipLabels.STOP_CAST}</slot>\n`\n);\nconst updateAriaLabel = (el) => {\n  const label = el.mediaIsCasting ? verbs.EXIT_CAST() : verbs.ENTER_CAST();\n  el.setAttribute(\"aria-label\", label);\n};\nclass MediaCastButton extends MediaChromeButton {\n  static get observedAttributes() {\n    return [\n      ...super.observedAttributes,\n      MediaUIAttributes.MEDIA_IS_CASTING,\n      MediaUIAttributes.MEDIA_CAST_UNAVAILABLE\n    ];\n  }\n  constructor(options = {}) {\n    super({ slotTemplate, tooltipContent, ...options });\n  }\n  connectedCallback() {\n    super.connectedCallback();\n    updateAriaLabel(this);\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    super.attributeChangedCallback(attrName, oldValue, newValue);\n    if (attrName === MediaUIAttributes.MEDIA_IS_CASTING) {\n      updateAriaLabel(this);\n    }\n  }\n  /**\n   * @type {boolean} Are we currently casting\n   */\n  get mediaIsCasting() {\n    return getBooleanAttr(this, MediaUIAttributes.MEDIA_IS_CASTING);\n  }\n  set mediaIsCasting(value) {\n    setBooleanAttr(this, MediaUIAttributes.MEDIA_IS_CASTING, value);\n  }\n  /**\n   * @type {string | undefined} Cast unavailability state\n   */\n  get mediaCastUnavailable() {\n    return getStringAttr(this, MediaUIAttributes.MEDIA_CAST_UNAVAILABLE);\n  }\n  set mediaCastUnavailable(value) {\n    setStringAttr(this, MediaUIAttributes.MEDIA_CAST_UNAVAILABLE, value);\n  }\n  handleClick() {\n    const eventName = this.mediaIsCasting ? MediaUIEvents.MEDIA_EXIT_CAST_REQUEST : MediaUIEvents.MEDIA_ENTER_CAST_REQUEST;\n    this.dispatchEvent(\n      new globalThis.CustomEvent(eventName, { composed: true, bubbles: true })\n    );\n  }\n}\nif (!globalThis.customElements.get(\"media-cast-button\")) {\n  globalThis.customElements.define(\"media-cast-button\", MediaCastButton);\n}\nvar media_cast_button_default = MediaCastButton;\nexport {\n  media_cast_button_default as default\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar __privateSet = (obj, member, value, setter) => {\n  __accessCheck(obj, member, \"write to private field\");\n  setter ? setter.call(obj, value) : member.set(obj, value);\n  return value;\n};\nvar __privateMethod = (obj, member, method) => {\n  __accessCheck(obj, member, \"access private method\");\n  return method;\n};\nvar _previouslyFocused, _invokerElement, _handleOpen, handleOpen_fn, _handleClosed, handleClosed_fn, _handleInvoke, handleInvoke_fn, _handleFocusOut, handleFocusOut_fn, _handleKeyDown, handleKeyDown_fn;\nimport { globalThis, document } from \"./utils/server-safe-globals.js\";\nimport {\n  containsComposedNode,\n  getActiveElement\n} from \"./utils/element-utils.js\";\nconst template = document.createElement(\"template\");\ntemplate.innerHTML = /*html*/\n`\n  <style>\n    :host {\n      font: var(--media-font,\n        var(--media-font-weight, normal)\n        var(--media-font-size, 14px) /\n        var(--media-text-content-height, var(--media-control-height, 24px))\n        var(--media-font-family, helvetica neue, segoe ui, roboto, arial, sans-serif));\n      color: var(--media-text-color, var(--media-primary-color, rgb(238 238 238)));\n      background: var(--media-dialog-background, var(--media-control-background, var(--media-secondary-color, rgb(20 20 30 / .8))));\n      border-radius: var(--media-dialog-border-radius);\n      border: var(--media-dialog-border, none);\n      display: var(--media-dialog-display, inline-flex);\n      transition: var(--media-dialog-transition-in,\n        visibility 0s,\n        opacity .2s ease-out,\n        transform .15s ease-out\n      ) !important;\n      ${/* ^^Prevent transition override by media-container */\n\"\"}\n      visibility: var(--media-dialog-visibility, visible);\n      opacity: var(--media-dialog-opacity, 1);\n      transform: var(--media-dialog-transform-in, translateY(0) scale(1));\n    }\n\n    :host([hidden]) {\n      transition: var(--media-dialog-transition-out,\n        visibility .15s ease-in,\n        opacity .15s ease-in,\n        transform .15s ease-in\n      ) !important;\n      visibility: var(--media-dialog-hidden-visibility, hidden);\n      opacity: var(--media-dialog-hidden-opacity, 0);\n      transform: var(--media-dialog-transform-out, translateY(2px) scale(.99));\n      pointer-events: none;\n    }\n  </style>\n  <slot></slot>\n`;\nconst Attributes = {\n  HIDDEN: \"hidden\",\n  ANCHOR: \"anchor\"\n};\nclass MediaChromeDialog extends globalThis.HTMLElement {\n  constructor() {\n    super();\n    __privateAdd(this, _handleOpen);\n    __privateAdd(this, _handleClosed);\n    __privateAdd(this, _handleInvoke);\n    __privateAdd(this, _handleFocusOut);\n    __privateAdd(this, _handleKeyDown);\n    __privateAdd(this, _previouslyFocused, null);\n    __privateAdd(this, _invokerElement, null);\n    if (!this.shadowRoot) {\n      this.attachShadow({ mode: \"open\" });\n      this.nativeEl = this.constructor.template.content.cloneNode(true);\n      this.shadowRoot.append(this.nativeEl);\n    }\n    this.addEventListener(\"invoke\", this);\n    this.addEventListener(\"focusout\", this);\n    this.addEventListener(\"keydown\", this);\n  }\n  static get observedAttributes() {\n    return [Attributes.HIDDEN, Attributes.ANCHOR];\n  }\n  handleEvent(event) {\n    switch (event.type) {\n      case \"invoke\":\n        __privateMethod(this, _handleInvoke, handleInvoke_fn).call(this, event);\n        break;\n      case \"focusout\":\n        __privateMethod(this, _handleFocusOut, handleFocusOut_fn).call(this, event);\n        break;\n      case \"keydown\":\n        __privateMethod(this, _handleKeyDown, handleKeyDown_fn).call(this, event);\n        break;\n    }\n  }\n  connectedCallback() {\n    if (!this.role) {\n      this.role = \"dialog\";\n    }\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    if (attrName === Attributes.HIDDEN && newValue !== oldValue) {\n      if (this.hidden) {\n        __privateMethod(this, _handleClosed, handleClosed_fn).call(this);\n      } else {\n        __privateMethod(this, _handleOpen, handleOpen_fn).call(this);\n      }\n    }\n  }\n  focus() {\n    __privateSet(this, _previouslyFocused, getActiveElement());\n    const focusable = this.querySelector(\n      '[autofocus], [tabindex]:not([tabindex=\"-1\"]), [role=\"menu\"]'\n    );\n    focusable == null ? void 0 : focusable.focus();\n  }\n  get keysUsed() {\n    return [\"Escape\", \"Tab\"];\n  }\n}\n_previouslyFocused = new WeakMap();\n_invokerElement = new WeakMap();\n_handleOpen = new WeakSet();\nhandleOpen_fn = function() {\n  var _a;\n  (_a = __privateGet(this, _invokerElement)) == null ? void 0 : _a.setAttribute(\"aria-expanded\", \"true\");\n  this.addEventListener(\"transitionend\", () => this.focus(), { once: true });\n};\n_handleClosed = new WeakSet();\nhandleClosed_fn = function() {\n  var _a;\n  (_a = __privateGet(this, _invokerElement)) == null ? void 0 : _a.setAttribute(\"aria-expanded\", \"false\");\n};\n_handleInvoke = new WeakSet();\nhandleInvoke_fn = function(event) {\n  __privateSet(this, _invokerElement, event.relatedTarget);\n  if (!containsComposedNode(this, event.relatedTarget)) {\n    this.hidden = !this.hidden;\n  }\n};\n_handleFocusOut = new WeakSet();\nhandleFocusOut_fn = function(event) {\n  var _a;\n  if (!containsComposedNode(this, event.relatedTarget)) {\n    (_a = __privateGet(this, _previouslyFocused)) == null ? void 0 : _a.focus();\n    if (__privateGet(this, _invokerElement) && __privateGet(this, _invokerElement) !== event.relatedTarget && !this.hidden) {\n      this.hidden = true;\n    }\n  }\n};\n_handleKeyDown = new WeakSet();\nhandleKeyDown_fn = function(event) {\n  var _a, _b, _c, _d, _e;\n  const { key, ctrlKey, altKey, metaKey } = event;\n  if (ctrlKey || altKey || metaKey) {\n    return;\n  }\n  if (!this.keysUsed.includes(key)) {\n    return;\n  }\n  event.preventDefault();\n  event.stopPropagation();\n  if (key === \"Tab\") {\n    if (event.shiftKey) {\n      (_b = (_a = this.previousElementSibling) == null ? void 0 : _a.focus) == null ? void 0 : _b.call(_a);\n    } else {\n      (_d = (_c = this.nextElementSibling) == null ? void 0 : _c.focus) == null ? void 0 : _d.call(_c);\n    }\n    this.blur();\n  } else if (key === \"Escape\") {\n    (_e = __privateGet(this, _previouslyFocused)) == null ? void 0 : _e.focus();\n    this.hidden = true;\n  }\n};\nMediaChromeDialog.template = template;\nif (!globalThis.customElements.get(\"media-chrome-dialog\")) {\n  globalThis.customElements.define(\"media-chrome-dialog\", MediaChromeDialog);\n}\nvar media_chrome_dialog_default = MediaChromeDialog;\nexport {\n  Attributes,\n  MediaChromeDialog,\n  media_chrome_dialog_default as default\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar __privateSet = (obj, member, value, setter) => {\n  __accessCheck(obj, member, \"write to private field\");\n  setter ? setter.call(obj, value) : member.set(obj, value);\n  return value;\n};\nvar __privateMethod = (obj, member, method) => {\n  __accessCheck(obj, member, \"access private method\");\n  return method;\n};\nvar _mediaController, _isInputTarget, _startpoint, _endpoint, _cssRules, _segments, _onFocusIn, _onFocusOut, _updateComputedStyles, _updateActiveSegment, updateActiveSegment_fn, _enableUserEvents, enableUserEvents_fn, _disableUserEvents, disableUserEvents_fn, _handlePointerDown, handlePointerDown_fn, _handlePointerEnter, handlePointerEnter_fn, _handlePointerUp, handlePointerUp_fn, _handlePointerLeave, handlePointerLeave_fn, _handlePointerMove, handlePointerMove_fn;\nimport { MediaStateReceiverAttributes } from \"./constants.js\";\nimport { globalThis, document } from \"./utils/server-safe-globals.js\";\nimport {\n  getOrInsertCSSRule,\n  getPointProgressOnLine\n} from \"./utils/element-utils.js\";\nimport { observeResize, unobserveResize } from \"./utils/resize-observer.js\";\nconst template = document.createElement(\"template\");\ntemplate.innerHTML = /*html*/\n`\n  <style>\n    :host {\n      --_focus-box-shadow: var(--media-focus-box-shadow, inset 0 0 0 2px rgb(27 127 204 / .9));\n      --_media-range-padding: var(--media-range-padding, var(--media-control-padding, 10px));\n\n      box-shadow: var(--_focus-visible-box-shadow, none);\n      background: var(--media-control-background, var(--media-secondary-color, rgb(20 20 30 / .7)));\n      height: calc(var(--media-control-height, 24px) + 2 * var(--_media-range-padding));\n      display: inline-flex;\n      align-items: center;\n      ${/* Don't horizontal align w/ justify-content! #container can go negative on the x-axis w/ small width. */\n\"\"}\n      vertical-align: middle;\n      box-sizing: border-box;\n      position: relative;\n      width: 100px;\n      transition: background .15s linear;\n      cursor: pointer;\n      pointer-events: auto;\n      touch-action: none; ${/* Prevent scrolling when dragging on mobile. */\n\"\"}\n      z-index: 1; ${/* Apply z-index to overlap buttons below. */\n\"\"}\n    }\n\n    ${/* Reset before `outline` on track could be set by a CSS var */\n\"\"}\n    input[type=range]:focus {\n      outline: 0;\n    }\n    input[type=range]:focus::-webkit-slider-runnable-track {\n      outline: 0;\n    }\n\n    :host(:hover) {\n      background: var(--media-control-hover-background, rgb(50 50 70 / .7));\n    }\n\n    #leftgap {\n      padding-left: var(--media-range-padding-left, var(--_media-range-padding));\n    }\n\n    #rightgap {\n      padding-right: var(--media-range-padding-right, var(--_media-range-padding));\n    }\n\n    #startpoint,\n    #endpoint {\n      position: absolute;\n    }\n\n    #endpoint {\n      right: 0;\n    }\n\n    #container {\n      ${/* Not using the CSS `padding` prop makes it easier for slide open volume ranges so the width can be zero. */\n\"\"}\n      width: var(--media-range-track-width, 100%);\n      transform: translate(var(--media-range-track-translate-x, 0px), var(--media-range-track-translate-y, 0px));\n      position: relative;\n      height: 100%;\n      display: flex;\n      align-items: center;\n      min-width: 40px;\n    }\n\n    #range {\n      ${/* The input range acts as a hover and hit zone for input events. */\n\"\"}\n      display: var(--media-time-range-hover-display, block);\n      bottom: var(--media-time-range-hover-bottom, -7px);\n      height: var(--media-time-range-hover-height, max(100% + 7px, 25px));\n      width: 100%;\n      position: absolute;\n      cursor: pointer;\n\n      -webkit-appearance: none; ${/* Hides the slider so that custom slider can be made */\n\"\"}\n      -webkit-tap-highlight-color: transparent;\n      background: transparent; ${/* Otherwise white in Chrome */\n\"\"}\n      margin: 0;\n      z-index: 1;\n    }\n\n    @media (hover: hover) {\n      #range {\n        bottom: var(--media-time-range-hover-bottom, -5px);\n        height: var(--media-time-range-hover-height, max(100% + 5px, 20px));\n      }\n    }\n\n    ${/* Special styling for WebKit/Blink */\n\"\"}\n    ${/* Make thumb width/height small so it has no effect on range click position. */\n\"\"}\n    #range::-webkit-slider-thumb {\n      -webkit-appearance: none;\n      background: transparent;\n      width: .1px;\n      height: .1px;\n    }\n\n    ${/* The thumb is not positioned relative to the track in Firefox */\n\"\"}\n    #range::-moz-range-thumb {\n      background: transparent;\n      border: transparent;\n      width: .1px;\n      height: .1px;\n    }\n\n    #appearance {\n      height: var(--media-range-track-height, 4px);\n      display: flex;\n      flex-direction: column;\n      justify-content: center;\n      width: 100%;\n      position: absolute;\n      ${/* Required for Safari to stop glitching track height on hover */\n\"\"}\n      will-change: transform;\n    }\n\n    #track {\n      background: var(--media-range-track-background, rgb(255 255 255 / .2));\n      border-radius: var(--media-range-track-border-radius, 1px);\n      border: var(--media-range-track-border, none);\n      outline: var(--media-range-track-outline);\n      outline-offset: var(--media-range-track-outline-offset);\n      backdrop-filter: var(--media-range-track-backdrop-filter);\n      -webkit-backdrop-filter: var(--media-range-track-backdrop-filter);\n      box-shadow: var(--media-range-track-box-shadow, none);\n      position: absolute;\n      width: 100%;\n      height: 100%;\n      overflow: hidden;\n    }\n\n    #progress,\n    #pointer {\n      position: absolute;\n      height: 100%;\n      will-change: width;\n    }\n\n    #progress {\n      background: var(--media-range-bar-color, var(--media-primary-color, rgb(238 238 238)));\n      transition: var(--media-range-track-transition);\n    }\n\n    #pointer {\n      background: var(--media-range-track-pointer-background);\n      border-right: var(--media-range-track-pointer-border-right);\n      transition: visibility .25s, opacity .25s;\n      visibility: hidden;\n      opacity: 0;\n    }\n\n    @media (hover: hover) {\n      :host(:hover) #pointer {\n        transition: visibility .5s, opacity .5s;\n        visibility: visible;\n        opacity: 1;\n      }\n    }\n\n    #thumb {\n      width: var(--media-range-thumb-width, 10px);\n      height: var(--media-range-thumb-height, 10px);\n      margin-left: calc(var(--media-range-thumb-width, 10px) / -2);\n      border: var(--media-range-thumb-border, none);\n      border-radius: var(--media-range-thumb-border-radius, 10px);\n      background: var(--media-range-thumb-background, var(--media-primary-color, rgb(238 238 238)));\n      box-shadow: var(--media-range-thumb-box-shadow, 1px 1px 1px transparent);\n      transition: var(--media-range-thumb-transition);\n      transform: var(--media-range-thumb-transform, none);\n      opacity: var(--media-range-thumb-opacity, 1);\n      position: absolute;\n      left: 0;\n      cursor: pointer;\n    }\n\n    :host([disabled]) #thumb {\n      background-color: #777;\n    }\n\n    .segments #appearance {\n      height: var(--media-range-segment-hover-height, 7px);\n    }\n\n    #track {\n      clip-path: url(#segments-clipping);\n    }\n\n    #segments {\n      --segments-gap: var(--media-range-segments-gap, 2px);\n      position: absolute;\n      width: 100%;\n      height: 100%;\n    }\n\n    #segments-clipping {\n      transform: translateX(calc(var(--segments-gap) / 2));\n    }\n\n    #segments-clipping:empty {\n      display: none;\n    }\n\n    #segments-clipping rect {\n      height: var(--media-range-track-height, 4px);\n      y: calc((var(--media-range-segment-hover-height, 7px) - var(--media-range-track-height, 4px)) / 2);\n      transition: var(--media-range-segment-transition, transform .1s ease-in-out);\n      transform: var(--media-range-segment-transform, scaleY(1));\n      transform-origin: center;\n    }\n  </style>\n  <div id=\"leftgap\"></div>\n  <div id=\"container\">\n    <div id=\"startpoint\"></div>\n    <div id=\"endpoint\"></div>\n    <div id=\"appearance\">\n      <div id=\"track\" part=\"track\">\n        <div id=\"pointer\"></div>\n        <div id=\"progress\" part=\"progress\"></div>\n      </div>\n      <div id=\"thumb\" part=\"thumb\"></div>\n      <svg id=\"segments\"><clipPath id=\"segments-clipping\"></clipPath></svg>\n    </div>\n    <input id=\"range\" type=\"range\" min=\"0\" max=\"1\" step=\"any\" value=\"0\">\n  </div>\n  <div id=\"rightgap\"></div>\n`;\nclass MediaChromeRange extends globalThis.HTMLElement {\n  constructor() {\n    super();\n    __privateAdd(this, _updateActiveSegment);\n    __privateAdd(this, _enableUserEvents);\n    __privateAdd(this, _disableUserEvents);\n    __privateAdd(this, _handlePointerDown);\n    __privateAdd(this, _handlePointerEnter);\n    __privateAdd(this, _handlePointerUp);\n    __privateAdd(this, _handlePointerLeave);\n    __privateAdd(this, _handlePointerMove);\n    __privateAdd(this, _mediaController, void 0);\n    __privateAdd(this, _isInputTarget, void 0);\n    __privateAdd(this, _startpoint, void 0);\n    __privateAdd(this, _endpoint, void 0);\n    __privateAdd(this, _cssRules, {});\n    __privateAdd(this, _segments, []);\n    __privateAdd(this, _onFocusIn, () => {\n      if (this.range.matches(\":focus-visible\")) {\n        const { style } = getOrInsertCSSRule(this.shadowRoot, \":host\");\n        style.setProperty(\n          \"--_focus-visible-box-shadow\",\n          \"var(--_focus-box-shadow)\"\n        );\n      }\n    });\n    __privateAdd(this, _onFocusOut, () => {\n      const { style } = getOrInsertCSSRule(this.shadowRoot, \":host\");\n      style.removeProperty(\"--_focus-visible-box-shadow\");\n    });\n    __privateAdd(this, _updateComputedStyles, () => {\n      const clipping = this.shadowRoot.querySelector(\"#segments-clipping\");\n      if (clipping)\n        clipping.parentNode.append(clipping);\n    });\n    if (!this.shadowRoot) {\n      this.attachShadow({ mode: \"open\" });\n      this.shadowRoot.appendChild(template.content.cloneNode(true));\n    }\n    this.container = this.shadowRoot.querySelector(\"#container\");\n    __privateSet(this, _startpoint, this.shadowRoot.querySelector(\"#startpoint\"));\n    __privateSet(this, _endpoint, this.shadowRoot.querySelector(\"#endpoint\"));\n    this.range = this.shadowRoot.querySelector(\"#range\");\n    this.appearance = this.shadowRoot.querySelector(\"#appearance\");\n  }\n  static get observedAttributes() {\n    return [\n      \"disabled\",\n      \"aria-disabled\",\n      MediaStateReceiverAttributes.MEDIA_CONTROLLER\n    ];\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    var _a, _b, _c, _d, _e;\n    if (attrName === MediaStateReceiverAttributes.MEDIA_CONTROLLER) {\n      if (oldValue) {\n        (_b = (_a = __privateGet(this, _mediaController)) == null ? void 0 : _a.unassociateElement) == null ? void 0 : _b.call(_a, this);\n        __privateSet(this, _mediaController, null);\n      }\n      if (newValue && this.isConnected) {\n        __privateSet(this, _mediaController, (_c = this.getRootNode()) == null ? void 0 : _c.getElementById(newValue));\n        (_e = (_d = __privateGet(this, _mediaController)) == null ? void 0 : _d.associateElement) == null ? void 0 : _e.call(_d, this);\n      }\n    } else if (attrName === \"disabled\" || attrName === \"aria-disabled\" && oldValue !== newValue) {\n      if (newValue == null) {\n        this.range.removeAttribute(attrName);\n        __privateMethod(this, _enableUserEvents, enableUserEvents_fn).call(this);\n      } else {\n        this.range.setAttribute(attrName, newValue);\n        __privateMethod(this, _disableUserEvents, disableUserEvents_fn).call(this);\n      }\n    }\n  }\n  connectedCallback() {\n    var _a, _b, _c;\n    const { style } = getOrInsertCSSRule(this.shadowRoot, \":host\");\n    style.setProperty(\n      \"display\",\n      `var(--media-control-display, var(--${this.localName}-display, inline-flex))`\n    );\n    __privateGet(this, _cssRules).pointer = getOrInsertCSSRule(this.shadowRoot, \"#pointer\");\n    __privateGet(this, _cssRules).progress = getOrInsertCSSRule(this.shadowRoot, \"#progress\");\n    __privateGet(this, _cssRules).thumb = getOrInsertCSSRule(this.shadowRoot, \"#thumb\");\n    __privateGet(this, _cssRules).activeSegment = getOrInsertCSSRule(\n      this.shadowRoot,\n      \"#segments-clipping rect:nth-child(0)\"\n    );\n    const mediaControllerId = this.getAttribute(\n      MediaStateReceiverAttributes.MEDIA_CONTROLLER\n    );\n    if (mediaControllerId) {\n      __privateSet(this, _mediaController, (_a = this.getRootNode()) == null ? void 0 : _a.getElementById(\n        mediaControllerId\n      ));\n      (_c = (_b = __privateGet(this, _mediaController)) == null ? void 0 : _b.associateElement) == null ? void 0 : _c.call(_b, this);\n    }\n    this.updateBar();\n    this.shadowRoot.addEventListener(\"focusin\", __privateGet(this, _onFocusIn));\n    this.shadowRoot.addEventListener(\"focusout\", __privateGet(this, _onFocusOut));\n    __privateMethod(this, _enableUserEvents, enableUserEvents_fn).call(this);\n    observeResize(this.container, __privateGet(this, _updateComputedStyles));\n  }\n  disconnectedCallback() {\n    var _a, _b;\n    __privateMethod(this, _disableUserEvents, disableUserEvents_fn).call(this);\n    (_b = (_a = __privateGet(this, _mediaController)) == null ? void 0 : _a.unassociateElement) == null ? void 0 : _b.call(_a, this);\n    __privateSet(this, _mediaController, null);\n    this.shadowRoot.removeEventListener(\"focusin\", __privateGet(this, _onFocusIn));\n    this.shadowRoot.removeEventListener(\"focusout\", __privateGet(this, _onFocusOut));\n    unobserveResize(this.container, __privateGet(this, _updateComputedStyles));\n  }\n  updatePointerBar(evt) {\n    var _a;\n    (_a = __privateGet(this, _cssRules).pointer) == null ? void 0 : _a.style.setProperty(\n      \"width\",\n      `${this.getPointerRatio(evt) * 100}%`\n    );\n  }\n  updateBar() {\n    var _a, _b;\n    const rangePercent = this.range.valueAsNumber * 100;\n    (_a = __privateGet(this, _cssRules).progress) == null ? void 0 : _a.style.setProperty(\"width\", `${rangePercent}%`);\n    (_b = __privateGet(this, _cssRules).thumb) == null ? void 0 : _b.style.setProperty(\"left\", `${rangePercent}%`);\n  }\n  updateSegments(segments) {\n    const clipping = this.shadowRoot.querySelector(\"#segments-clipping\");\n    clipping.textContent = \"\";\n    this.container.classList.toggle(\"segments\", !!(segments == null ? void 0 : segments.length));\n    if (!(segments == null ? void 0 : segments.length))\n      return;\n    const normalized = [\n      .../* @__PURE__ */ new Set([\n        +this.range.min,\n        ...segments.flatMap((s) => [s.start, s.end]),\n        +this.range.max\n      ])\n    ];\n    __privateSet(this, _segments, [...normalized]);\n    const lastMarker = normalized.pop();\n    for (const [i, marker] of normalized.entries()) {\n      const [isFirst, isLast] = [i === 0, i === normalized.length - 1];\n      const x = isFirst ? \"calc(var(--segments-gap) / -1)\" : `${marker * 100}%`;\n      const x2 = isLast ? lastMarker : normalized[i + 1];\n      const width = `calc(${(x2 - marker) * 100}%${isFirst || isLast ? \"\" : ` - var(--segments-gap)`})`;\n      const segmentEl = document.createElementNS(\n        \"http://www.w3.org/2000/svg\",\n        \"rect\"\n      );\n      const cssRule = getOrInsertCSSRule(\n        this.shadowRoot,\n        `#segments-clipping rect:nth-child(${i + 1})`\n      );\n      cssRule.style.setProperty(\"x\", x);\n      cssRule.style.setProperty(\"width\", width);\n      clipping.append(segmentEl);\n    }\n  }\n  getPointerRatio(evt) {\n    const pointerRatio = getPointProgressOnLine(\n      evt.clientX,\n      evt.clientY,\n      __privateGet(this, _startpoint).getBoundingClientRect(),\n      __privateGet(this, _endpoint).getBoundingClientRect()\n    );\n    return Math.max(0, Math.min(1, pointerRatio));\n  }\n  get dragging() {\n    return this.hasAttribute(\"dragging\");\n  }\n  handleEvent(evt) {\n    switch (evt.type) {\n      case \"pointermove\":\n        __privateMethod(this, _handlePointerMove, handlePointerMove_fn).call(this, evt);\n        break;\n      case \"input\":\n        this.updateBar();\n        break;\n      case \"pointerenter\":\n        __privateMethod(this, _handlePointerEnter, handlePointerEnter_fn).call(this, evt);\n        break;\n      case \"pointerdown\":\n        __privateMethod(this, _handlePointerDown, handlePointerDown_fn).call(this, evt);\n        break;\n      case \"pointerup\":\n        __privateMethod(this, _handlePointerUp, handlePointerUp_fn).call(this);\n        break;\n      case \"pointerleave\":\n        __privateMethod(this, _handlePointerLeave, handlePointerLeave_fn).call(this);\n        break;\n    }\n  }\n  get keysUsed() {\n    return [\"ArrowUp\", \"ArrowRight\", \"ArrowDown\", \"ArrowLeft\"];\n  }\n}\n_mediaController = new WeakMap();\n_isInputTarget = new WeakMap();\n_startpoint = new WeakMap();\n_endpoint = new WeakMap();\n_cssRules = new WeakMap();\n_segments = new WeakMap();\n_onFocusIn = new WeakMap();\n_onFocusOut = new WeakMap();\n_updateComputedStyles = new WeakMap();\n_updateActiveSegment = new WeakSet();\nupdateActiveSegment_fn = function(evt) {\n  const rule = __privateGet(this, _cssRules).activeSegment;\n  if (!rule)\n    return;\n  const pointerRatio = this.getPointerRatio(evt);\n  const segmentIndex = __privateGet(this, _segments).findIndex((start, i, arr) => {\n    const end = arr[i + 1];\n    return end != null && pointerRatio >= start && pointerRatio <= end;\n  });\n  const selectorText = `#segments-clipping rect:nth-child(${segmentIndex + 1})`;\n  if (rule.selectorText != selectorText || !rule.style.transform) {\n    rule.selectorText = selectorText;\n    rule.style.setProperty(\n      \"transform\",\n      \"var(--media-range-segment-hover-transform, scaleY(2))\"\n    );\n  }\n};\n_enableUserEvents = new WeakSet();\nenableUserEvents_fn = function() {\n  if (this.hasAttribute(\"disabled\"))\n    return;\n  this.addEventListener(\"input\", this);\n  this.addEventListener(\"pointerdown\", this);\n  this.addEventListener(\"pointerenter\", this);\n};\n_disableUserEvents = new WeakSet();\ndisableUserEvents_fn = function() {\n  var _a, _b;\n  this.removeEventListener(\"input\", this);\n  this.removeEventListener(\"pointerdown\", this);\n  this.removeEventListener(\"pointerenter\", this);\n  (_a = globalThis.window) == null ? void 0 : _a.removeEventListener(\"pointerup\", this);\n  (_b = globalThis.window) == null ? void 0 : _b.removeEventListener(\"pointermove\", this);\n};\n_handlePointerDown = new WeakSet();\nhandlePointerDown_fn = function(evt) {\n  var _a;\n  __privateSet(this, _isInputTarget, evt.composedPath().includes(this.range));\n  (_a = globalThis.window) == null ? void 0 : _a.addEventListener(\"pointerup\", this);\n};\n_handlePointerEnter = new WeakSet();\nhandlePointerEnter_fn = function(evt) {\n  var _a;\n  if (evt.pointerType !== \"mouse\")\n    __privateMethod(this, _handlePointerDown, handlePointerDown_fn).call(this, evt);\n  this.addEventListener(\"pointerleave\", this);\n  (_a = globalThis.window) == null ? void 0 : _a.addEventListener(\"pointermove\", this);\n};\n_handlePointerUp = new WeakSet();\nhandlePointerUp_fn = function() {\n  var _a;\n  (_a = globalThis.window) == null ? void 0 : _a.removeEventListener(\"pointerup\", this);\n  this.toggleAttribute(\"dragging\", false);\n  this.range.disabled = this.hasAttribute(\"disabled\");\n};\n_handlePointerLeave = new WeakSet();\nhandlePointerLeave_fn = function() {\n  var _a, _b;\n  this.removeEventListener(\"pointerleave\", this);\n  (_a = globalThis.window) == null ? void 0 : _a.removeEventListener(\"pointermove\", this);\n  this.toggleAttribute(\"dragging\", false);\n  this.range.disabled = this.hasAttribute(\"disabled\");\n  (_b = __privateGet(this, _cssRules).activeSegment) == null ? void 0 : _b.style.removeProperty(\"transform\");\n};\n_handlePointerMove = new WeakSet();\nhandlePointerMove_fn = function(evt) {\n  this.toggleAttribute(\n    \"dragging\",\n    evt.buttons === 1 || evt.pointerType !== \"mouse\"\n  );\n  this.updatePointerBar(evt);\n  __privateMethod(this, _updateActiveSegment, updateActiveSegment_fn).call(this, evt);\n  if (this.dragging && (evt.pointerType !== \"mouse\" || !__privateGet(this, _isInputTarget))) {\n    this.range.disabled = true;\n    this.range.valueAsNumber = this.getPointerRatio(evt);\n    this.range.dispatchEvent(\n      new Event(\"input\", { bubbles: true, composed: true })\n    );\n  }\n};\nif (!globalThis.customElements.get(\"media-chrome-range\")) {\n  globalThis.customElements.define(\"media-chrome-range\", MediaChromeRange);\n}\nvar media_chrome_range_default = MediaChromeRange;\nexport {\n  MediaChromeRange,\n  media_chrome_range_default as default\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar __privateSet = (obj, member, value, setter) => {\n  __accessCheck(obj, member, \"write to private field\");\n  setter ? setter.call(obj, value) : member.set(obj, value);\n  return value;\n};\nvar _mediaController;\nimport { MediaStateReceiverAttributes } from \"./constants.js\";\nimport { document, globalThis } from \"./utils/server-safe-globals.js\";\nconst template = document.createElement(\"template\");\ntemplate.innerHTML = /*html*/\n`\n  <style>\n    :host {\n      ${/* Need position to display above video for some reason */\n\"\"}\n      box-sizing: border-box;\n      display: var(--media-control-display, var(--media-control-bar-display, inline-flex));\n      color: var(--media-text-color, var(--media-primary-color, rgb(238 238 238)));\n      --media-loading-indicator-icon-height: 44px;\n    }\n\n    ::slotted(media-time-range),\n    ::slotted(media-volume-range) {\n      min-height: 100%;\n    }\n\n    ::slotted(media-time-range),\n    ::slotted(media-clip-selector) {\n      flex-grow: 1;\n    }\n\n    ::slotted([role=\"menu\"]) {\n      position: absolute;\n    }\n  </style>\n\n  <slot></slot>\n`;\nclass MediaControlBar extends globalThis.HTMLElement {\n  constructor() {\n    super();\n    __privateAdd(this, _mediaController, void 0);\n    if (!this.shadowRoot) {\n      this.attachShadow({ mode: \"open\" });\n      this.shadowRoot.appendChild(template.content.cloneNode(true));\n    }\n  }\n  static get observedAttributes() {\n    return [MediaStateReceiverAttributes.MEDIA_CONTROLLER];\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    var _a, _b, _c, _d, _e;\n    if (attrName === MediaStateReceiverAttributes.MEDIA_CONTROLLER) {\n      if (oldValue) {\n        (_b = (_a = __privateGet(this, _mediaController)) == null ? void 0 : _a.unassociateElement) == null ? void 0 : _b.call(_a, this);\n        __privateSet(this, _mediaController, null);\n      }\n      if (newValue && this.isConnected) {\n        __privateSet(this, _mediaController, (_c = this.getRootNode()) == null ? void 0 : _c.getElementById(newValue));\n        (_e = (_d = __privateGet(this, _mediaController)) == null ? void 0 : _d.associateElement) == null ? void 0 : _e.call(_d, this);\n      }\n    }\n  }\n  connectedCallback() {\n    var _a, _b, _c;\n    const mediaControllerId = this.getAttribute(\n      MediaStateReceiverAttributes.MEDIA_CONTROLLER\n    );\n    if (mediaControllerId) {\n      __privateSet(this, _mediaController, (_a = this.getRootNode()) == null ? void 0 : _a.getElementById(\n        mediaControllerId\n      ));\n      (_c = (_b = __privateGet(this, _mediaController)) == null ? void 0 : _b.associateElement) == null ? void 0 : _c.call(_b, this);\n    }\n  }\n  disconnectedCallback() {\n    var _a, _b;\n    (_b = (_a = __privateGet(this, _mediaController)) == null ? void 0 : _a.unassociateElement) == null ? void 0 : _b.call(_a, this);\n    __privateSet(this, _mediaController, null);\n  }\n}\n_mediaController = new WeakMap();\nif (!globalThis.customElements.get(\"media-control-bar\")) {\n  globalThis.customElements.define(\"media-control-bar\", MediaControlBar);\n}\nvar media_control_bar_default = MediaControlBar;\nexport {\n  media_control_bar_default as default\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar __privateSet = (obj, member, value, setter) => {\n  __accessCheck(obj, member, \"write to private field\");\n  setter ? setter.call(obj, value) : member.set(obj, value);\n  return value;\n};\nvar _mediaController;\nimport { MediaStateReceiverAttributes } from \"./constants.js\";\nimport { getOrInsertCSSRule } from \"./utils/element-utils.js\";\nimport { globalThis, document } from \"./utils/server-safe-globals.js\";\nconst template = document.createElement(\"template\");\ntemplate.innerHTML = /*html*/\n`\n  <style>\n    :host {\n      font: var(--media-font,\n        var(--media-font-weight, normal)\n        var(--media-font-size, 14px) /\n        var(--media-text-content-height, var(--media-control-height, 24px))\n        var(--media-font-family, helvetica neue, segoe ui, roboto, arial, sans-serif));\n      color: var(--media-text-color, var(--media-primary-color, rgb(238 238 238)));\n      background: var(--media-text-background, var(--media-control-background, var(--media-secondary-color, rgb(20 20 30 / .7))));\n      padding: var(--media-control-padding, 10px);\n      display: inline-flex;\n      justify-content: center;\n      align-items: center;\n      vertical-align: middle;\n      box-sizing: border-box;\n      text-align: center;\n      pointer-events: auto;\n    }\n\n    ${/*\n  Only show outline when keyboard focusing.\n  https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo\n*/\n\"\"}\n    :host(:focus-visible) {\n      box-shadow: inset 0 0 0 2px rgb(27 127 204 / .9);\n      outline: 0;\n    }\n\n    ${/*\n * hide default focus ring, particularly when using mouse\n */\n\"\"}\n    :host(:where(:focus)) {\n      box-shadow: none;\n      outline: 0;\n    }\n  </style>\n  <slot></slot>\n`;\nclass MediaTextDisplay extends globalThis.HTMLElement {\n  constructor() {\n    super();\n    __privateAdd(this, _mediaController, void 0);\n    if (!this.shadowRoot) {\n      this.attachShadow({ mode: \"open\" });\n      this.shadowRoot.appendChild(template.content.cloneNode(true));\n    }\n  }\n  static get observedAttributes() {\n    return [MediaStateReceiverAttributes.MEDIA_CONTROLLER];\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    var _a, _b, _c, _d, _e;\n    if (attrName === MediaStateReceiverAttributes.MEDIA_CONTROLLER) {\n      if (oldValue) {\n        (_b = (_a = __privateGet(this, _mediaController)) == null ? void 0 : _a.unassociateElement) == null ? void 0 : _b.call(_a, this);\n        __privateSet(this, _mediaController, null);\n      }\n      if (newValue && this.isConnected) {\n        __privateSet(this, _mediaController, (_c = this.getRootNode()) == null ? void 0 : _c.getElementById(newValue));\n        (_e = (_d = __privateGet(this, _mediaController)) == null ? void 0 : _d.associateElement) == null ? void 0 : _e.call(_d, this);\n      }\n    }\n  }\n  connectedCallback() {\n    var _a, _b, _c;\n    const { style } = getOrInsertCSSRule(this.shadowRoot, \":host\");\n    style.setProperty(\n      \"display\",\n      `var(--media-control-display, var(--${this.localName}-display, inline-flex))`\n    );\n    const mediaControllerId = this.getAttribute(\n      MediaStateReceiverAttributes.MEDIA_CONTROLLER\n    );\n    if (mediaControllerId) {\n      __privateSet(this, _mediaController, (_a = this.getRootNode()) == null ? void 0 : _a.getElementById(\n        mediaControllerId\n      ));\n      (_c = (_b = __privateGet(this, _mediaController)) == null ? void 0 : _b.associateElement) == null ? void 0 : _c.call(_b, this);\n    }\n  }\n  disconnectedCallback() {\n    var _a, _b;\n    (_b = (_a = __privateGet(this, _mediaController)) == null ? void 0 : _a.unassociateElement) == null ? void 0 : _b.call(_a, this);\n    __privateSet(this, _mediaController, null);\n  }\n}\n_mediaController = new WeakMap();\nif (!globalThis.customElements.get(\"media-text-display\")) {\n  globalThis.customElements.define(\"media-text-display\", MediaTextDisplay);\n}\nvar media_text_display_default = MediaTextDisplay;\nexport {\n  MediaTextDisplay,\n  media_text_display_default as default\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar __privateSet = (obj, member, value, setter) => {\n  __accessCheck(obj, member, \"write to private field\");\n  setter ? setter.call(obj, value) : member.set(obj, value);\n  return value;\n};\nvar _slot;\nimport { MediaTextDisplay } from \"./media-text-display.js\";\nimport { globalThis } from \"./utils/server-safe-globals.js\";\nimport { formatTime } from \"./utils/time.js\";\nimport { MediaUIAttributes } from \"./constants.js\";\nimport { getNumericAttr, setNumericAttr } from \"./utils/element-utils.js\";\nclass MediaDurationDisplay extends MediaTextDisplay {\n  constructor() {\n    super();\n    /** @type {HTMLSlotElement} */\n    __privateAdd(this, _slot, void 0);\n    __privateSet(this, _slot, this.shadowRoot.querySelector(\"slot\"));\n    __privateGet(this, _slot).textContent = formatTime(0);\n  }\n  static get observedAttributes() {\n    return [...super.observedAttributes, MediaUIAttributes.MEDIA_DURATION];\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    if (attrName === MediaUIAttributes.MEDIA_DURATION) {\n      __privateGet(this, _slot).textContent = formatTime(+newValue);\n    }\n    super.attributeChangedCallback(attrName, oldValue, newValue);\n  }\n  /**\n   * @type {number | undefined} In seconds\n   */\n  get mediaDuration() {\n    return getNumericAttr(this, MediaUIAttributes.MEDIA_DURATION);\n  }\n  set mediaDuration(time) {\n    setNumericAttr(this, MediaUIAttributes.MEDIA_DURATION, time);\n  }\n}\n_slot = new WeakMap();\nif (!globalThis.customElements.get(\"media-duration-display\")) {\n  globalThis.customElements.define(\n    \"media-duration-display\",\n    MediaDurationDisplay\n  );\n}\nvar media_duration_display_default = MediaDurationDisplay;\nexport {\n  media_duration_display_default as default\n};\n", "import { MediaChromeButton } from \"./media-chrome-button.js\";\nimport { globalThis, document } from \"./utils/server-safe-globals.js\";\nimport { MediaUIEvents, MediaUIAttributes } from \"./constants.js\";\nimport { tooltipLabels, verbs } from \"./labels/labels.js\";\nimport {\n  getBooleanAttr,\n  getStringAttr,\n  setBooleanAttr,\n  setStringAttr\n} from \"./utils/element-utils.js\";\nconst enterFullscreenIcon = `<svg aria-hidden=\"true\" viewBox=\"0 0 26 24\">\n  <path d=\"M16 3v2.5h3.5V9H22V3h-6ZM4 9h2.5V5.5H10V3H4v6Zm15.5 9.5H16V21h6v-6h-2.5v3.5ZM6.5 15H4v6h6v-2.5H6.5V15Z\"/>\n</svg>`;\nconst exitFullscreenIcon = `<svg aria-hidden=\"true\" viewBox=\"0 0 26 24\">\n  <path d=\"M18.5 6.5V3H16v6h6V6.5h-3.5ZM16 21h2.5v-3.5H22V15h-6v6ZM4 17.5h3.5V21H10v-6H4v2.5Zm3.5-11H4V9h6V3H7.5v3.5Z\"/>\n</svg>`;\nconst slotTemplate = document.createElement(\"template\");\nslotTemplate.innerHTML = /*html*/\n`\n  <style>\n    :host([${MediaUIAttributes.MEDIA_IS_FULLSCREEN}]) slot[name=icon] slot:not([name=exit]) {\n      display: none !important;\n    }\n\n    ${/* Double negative, but safer if display doesn't equal 'block' */\n\"\"}\n    :host(:not([${MediaUIAttributes.MEDIA_IS_FULLSCREEN}])) slot[name=icon] slot:not([name=enter]) {\n      display: none !important;\n    }\n\n    :host([${MediaUIAttributes.MEDIA_IS_FULLSCREEN}]) slot[name=tooltip-enter],\n    :host(:not([${MediaUIAttributes.MEDIA_IS_FULLSCREEN}])) slot[name=tooltip-exit] {\n      display: none;\n    }\n  </style>\n\n  <slot name=\"icon\">\n    <slot name=\"enter\">${enterFullscreenIcon}</slot>\n    <slot name=\"exit\">${exitFullscreenIcon}</slot>\n  </slot>\n`;\nconst tooltipContent = (\n  /*html*/\n  `\n  <slot name=\"tooltip-enter\">${tooltipLabels.ENTER_FULLSCREEN}</slot>\n  <slot name=\"tooltip-exit\">${tooltipLabels.EXIT_FULLSCREEN}</slot>\n`\n);\nconst updateAriaLabel = (el) => {\n  const label = el.mediaIsFullscreen ? verbs.EXIT_FULLSCREEN() : verbs.ENTER_FULLSCREEN();\n  el.setAttribute(\"aria-label\", label);\n};\nclass MediaFullscreenButton extends MediaChromeButton {\n  static get observedAttributes() {\n    return [\n      ...super.observedAttributes,\n      MediaUIAttributes.MEDIA_IS_FULLSCREEN,\n      MediaUIAttributes.MEDIA_FULLSCREEN_UNAVAILABLE\n    ];\n  }\n  constructor(options = {}) {\n    super({ slotTemplate, tooltipContent, ...options });\n  }\n  connectedCallback() {\n    super.connectedCallback();\n    updateAriaLabel(this);\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    super.attributeChangedCallback(attrName, oldValue, newValue);\n    if (attrName === MediaUIAttributes.MEDIA_IS_FULLSCREEN) {\n      updateAriaLabel(this);\n    }\n  }\n  /**\n   * @type {string | undefined} Fullscreen unavailability state\n   */\n  get mediaFullscreenUnavailable() {\n    return getStringAttr(this, MediaUIAttributes.MEDIA_FULLSCREEN_UNAVAILABLE);\n  }\n  set mediaFullscreenUnavailable(value) {\n    setStringAttr(this, MediaUIAttributes.MEDIA_FULLSCREEN_UNAVAILABLE, value);\n  }\n  /**\n   * @type {boolean} Whether fullscreen is available\n   */\n  get mediaIsFullscreen() {\n    return getBooleanAttr(this, MediaUIAttributes.MEDIA_IS_FULLSCREEN);\n  }\n  set mediaIsFullscreen(value) {\n    setBooleanAttr(this, MediaUIAttributes.MEDIA_IS_FULLSCREEN, value);\n  }\n  handleClick() {\n    const eventName = this.mediaIsFullscreen ? MediaUIEvents.MEDIA_EXIT_FULLSCREEN_REQUEST : MediaUIEvents.MEDIA_ENTER_FULLSCREEN_REQUEST;\n    this.dispatchEvent(\n      new globalThis.CustomEvent(eventName, { composed: true, bubbles: true })\n    );\n  }\n}\nif (!globalThis.customElements.get(\"media-fullscreen-button\")) {\n  globalThis.customElements.define(\n    \"media-fullscreen-button\",\n    MediaFullscreenButton\n  );\n}\nvar media_fullscreen_button_default = MediaFullscreenButton;\nexport {\n  media_fullscreen_button_default as default\n};\n", "import { MediaChromeButton } from \"./media-chrome-button.js\";\nimport { globalThis, document } from \"./utils/server-safe-globals.js\";\nimport { MediaUIEvents, MediaUIAttributes } from \"./constants.js\";\nimport { verbs } from \"./labels/labels.js\";\nimport { getBooleanAttr, setBooleanAttr } from \"./utils/element-utils.js\";\nconst { MEDIA_TIME_IS_LIVE, MEDIA_PAUSED } = MediaUIAttributes;\nconst { MEDIA_SEEK_TO_LIVE_REQUEST, MEDIA_PLAY_REQUEST } = MediaUIEvents;\nconst indicatorSVG = '<svg viewBox=\"0 0 6 12\"><circle cx=\"3\" cy=\"6\" r=\"2\"></circle></svg>';\nconst slotTemplate = document.createElement(\"template\");\nslotTemplate.innerHTML = /*html*/\n`\n  <style>\n  :host { --media-tooltip-display: none; }\n  \n  slot[name=indicator] > *,\n  :host ::slotted([slot=indicator]) {\n    ${/* Override styles for icon-only buttons */\n\"\"}\n    min-width: auto;\n    fill: var(--media-live-button-icon-color, rgb(140, 140, 140));\n    color: var(--media-live-button-icon-color, rgb(140, 140, 140));\n  }\n\n  :host([${MEDIA_TIME_IS_LIVE}]:not([${MEDIA_PAUSED}])) slot[name=indicator] > *,\n  :host([${MEDIA_TIME_IS_LIVE}]:not([${MEDIA_PAUSED}])) ::slotted([slot=indicator]) {\n    fill: var(--media-live-button-indicator-color, rgb(255, 0, 0));\n    color: var(--media-live-button-indicator-color, rgb(255, 0, 0));\n  }\n\n  :host([${MEDIA_TIME_IS_LIVE}]:not([${MEDIA_PAUSED}])) {\n    cursor: not-allowed;\n  }\n\n  </style>\n\n  <slot name=\"indicator\">${indicatorSVG}</slot>\n  ${/*\n  A new line between spacer and text creates inconsistent spacing\n  between slotted items and default slots.\n*/\n\"\"}\n  <slot name=\"spacer\">&nbsp;</slot><slot name=\"text\">LIVE</slot>\n`;\nconst updateAriaAttributes = (el) => {\n  const isPausedOrNotLive = el.mediaPaused || !el.mediaTimeIsLive;\n  const label = isPausedOrNotLive ? verbs.SEEK_LIVE() : verbs.PLAYING_LIVE();\n  el.setAttribute(\"aria-label\", label);\n  isPausedOrNotLive ? el.removeAttribute(\"aria-disabled\") : el.setAttribute(\"aria-disabled\", \"true\");\n};\nclass MediaLiveButton extends MediaChromeButton {\n  static get observedAttributes() {\n    return [...super.observedAttributes, MEDIA_PAUSED, MEDIA_TIME_IS_LIVE];\n  }\n  constructor(options = {}) {\n    super({ slotTemplate, ...options });\n  }\n  connectedCallback() {\n    updateAriaAttributes(this);\n    super.connectedCallback();\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    super.attributeChangedCallback(attrName, oldValue, newValue);\n    updateAriaAttributes(this);\n  }\n  /**\n   * @type {boolean} Is the media paused\n   */\n  get mediaPaused() {\n    return getBooleanAttr(this, MediaUIAttributes.MEDIA_PAUSED);\n  }\n  set mediaPaused(value) {\n    setBooleanAttr(this, MediaUIAttributes.MEDIA_PAUSED, value);\n  }\n  /**\n   * @type {boolean} Is the media playback currently live\n   */\n  get mediaTimeIsLive() {\n    return getBooleanAttr(this, MediaUIAttributes.MEDIA_TIME_IS_LIVE);\n  }\n  set mediaTimeIsLive(value) {\n    setBooleanAttr(this, MediaUIAttributes.MEDIA_TIME_IS_LIVE, value);\n  }\n  handleClick() {\n    if (!this.mediaPaused && this.mediaTimeIsLive)\n      return;\n    this.dispatchEvent(\n      new globalThis.CustomEvent(MEDIA_SEEK_TO_LIVE_REQUEST, {\n        composed: true,\n        bubbles: true\n      })\n    );\n    if (this.hasAttribute(MEDIA_PAUSED)) {\n      this.dispatchEvent(\n        new globalThis.CustomEvent(MEDIA_PLAY_REQUEST, {\n          composed: true,\n          bubbles: true\n        })\n      );\n    }\n  }\n}\nif (!globalThis.customElements.get(\"media-live-button\")) {\n  globalThis.customElements.define(\"media-live-button\", MediaLiveButton);\n}\nvar media_live_button_default = MediaLiveButton;\nexport {\n  media_live_button_default as default\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar __privateSet = (obj, member, value, setter) => {\n  __accessCheck(obj, member, \"write to private field\");\n  setter ? setter.call(obj, value) : member.set(obj, value);\n  return value;\n};\nvar _mediaController, _delay;\nimport {\n  MediaUIAttributes,\n  MediaStateReceiverAttributes\n} from \"./constants.js\";\nimport { nouns } from \"./labels/labels.js\";\nimport { globalThis, document } from \"./utils/server-safe-globals.js\";\nimport {\n  getBooleanAttr,\n  setBooleanAttr,\n  getOrInsertCSSRule\n} from \"./utils/element-utils.js\";\nconst Attributes = {\n  LOADING_DELAY: \"loadingdelay\"\n};\nconst DEFAULT_LOADING_DELAY = 500;\nconst template = document.createElement(\"template\");\nconst loadingIndicatorIcon = `\n<svg aria-hidden=\"true\" viewBox=\"0 0 100 100\">\n  <path d=\"M73,50c0-12.7-10.3-23-23-23S27,37.3,27,50 M30.9,50c0-10.5,8.5-19.1,19.1-19.1S69.1,39.5,69.1,50\">\n    <animateTransform\n       attributeName=\"transform\"\n       attributeType=\"XML\"\n       type=\"rotate\"\n       dur=\"1s\"\n       from=\"0 50 50\"\n       to=\"360 50 50\"\n       repeatCount=\"indefinite\" />\n  </path>\n</svg>\n`;\ntemplate.innerHTML = /*html*/\n`\n<style>\n:host {\n  display: var(--media-control-display, var(--media-loading-indicator-display, inline-block));\n  vertical-align: middle;\n  box-sizing: border-box;\n  --_loading-indicator-delay: var(--media-loading-indicator-transition-delay, ${DEFAULT_LOADING_DELAY}ms);\n}\n\n#status {\n  color: rgba(0,0,0,0);\n  width: 0px;\n  height: 0px;\n}\n\n:host slot[name=icon] > *,\n:host ::slotted([slot=icon]) {\n  opacity: var(--media-loading-indicator-opacity, 0);\n  transition: opacity 0.15s;\n}\n\n:host([${MediaUIAttributes.MEDIA_LOADING}]:not([${MediaUIAttributes.MEDIA_PAUSED}])) slot[name=icon] > *,\n:host([${MediaUIAttributes.MEDIA_LOADING}]:not([${MediaUIAttributes.MEDIA_PAUSED}])) ::slotted([slot=icon]) {\n  opacity: var(--media-loading-indicator-opacity, 1);\n  transition: opacity 0.15s var(--_loading-indicator-delay);\n}\n\n:host #status {\n  visibility: var(--media-loading-indicator-opacity, hidden);\n  transition: visibility 0.15s;\n}\n\n:host([${MediaUIAttributes.MEDIA_LOADING}]:not([${MediaUIAttributes.MEDIA_PAUSED}])) #status {\n  visibility: var(--media-loading-indicator-opacity, visible);\n  transition: visibility 0.15s var(--_loading-indicator-delay);\n}\n\nsvg, img, ::slotted(svg), ::slotted(img) {\n  width: var(--media-loading-indicator-icon-width);\n  height: var(--media-loading-indicator-icon-height, 100px);\n  fill: var(--media-icon-color, var(--media-primary-color, rgb(238 238 238)));\n  vertical-align: middle;\n}\n</style>\n\n<slot name=\"icon\">${loadingIndicatorIcon}</slot>\n<div id=\"status\" role=\"status\" aria-live=\"polite\">${nouns.MEDIA_LOADING()}</div>\n`;\nclass MediaLoadingIndicator extends globalThis.HTMLElement {\n  constructor() {\n    super();\n    __privateAdd(this, _mediaController, void 0);\n    __privateAdd(this, _delay, DEFAULT_LOADING_DELAY);\n    if (!this.shadowRoot) {\n      const shadow = this.attachShadow({ mode: \"open\" });\n      const indicatorHTML = template.content.cloneNode(true);\n      shadow.appendChild(indicatorHTML);\n    }\n  }\n  static get observedAttributes() {\n    return [\n      MediaStateReceiverAttributes.MEDIA_CONTROLLER,\n      MediaUIAttributes.MEDIA_PAUSED,\n      MediaUIAttributes.MEDIA_LOADING,\n      Attributes.LOADING_DELAY\n    ];\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    var _a, _b, _c, _d, _e;\n    if (attrName === Attributes.LOADING_DELAY && oldValue !== newValue) {\n      this.loadingDelay = Number(newValue);\n    } else if (attrName === MediaStateReceiverAttributes.MEDIA_CONTROLLER) {\n      if (oldValue) {\n        (_b = (_a = __privateGet(this, _mediaController)) == null ? void 0 : _a.unassociateElement) == null ? void 0 : _b.call(_a, this);\n        __privateSet(this, _mediaController, null);\n      }\n      if (newValue && this.isConnected) {\n        __privateSet(this, _mediaController, (_c = this.getRootNode()) == null ? void 0 : _c.getElementById(newValue));\n        (_e = (_d = __privateGet(this, _mediaController)) == null ? void 0 : _d.associateElement) == null ? void 0 : _e.call(_d, this);\n      }\n    }\n  }\n  connectedCallback() {\n    var _a, _b, _c;\n    const mediaControllerId = this.getAttribute(\n      MediaStateReceiverAttributes.MEDIA_CONTROLLER\n    );\n    if (mediaControllerId) {\n      __privateSet(this, _mediaController, (_a = this.getRootNode()) == null ? void 0 : _a.getElementById(\n        mediaControllerId\n      ));\n      (_c = (_b = __privateGet(this, _mediaController)) == null ? void 0 : _b.associateElement) == null ? void 0 : _c.call(_b, this);\n    }\n  }\n  disconnectedCallback() {\n    var _a, _b;\n    (_b = (_a = __privateGet(this, _mediaController)) == null ? void 0 : _a.unassociateElement) == null ? void 0 : _b.call(_a, this);\n    __privateSet(this, _mediaController, null);\n  }\n  /**\n   * Delay in ms\n   */\n  get loadingDelay() {\n    return __privateGet(this, _delay);\n  }\n  set loadingDelay(delay) {\n    __privateSet(this, _delay, delay);\n    const { style } = getOrInsertCSSRule(this.shadowRoot, \":host\");\n    style.setProperty(\n      \"--_loading-indicator-delay\",\n      `var(--media-loading-indicator-transition-delay, ${delay}ms)`\n    );\n  }\n  /**\n   * Is the media paused\n   */\n  get mediaPaused() {\n    return getBooleanAttr(this, MediaUIAttributes.MEDIA_PAUSED);\n  }\n  set mediaPaused(value) {\n    setBooleanAttr(this, MediaUIAttributes.MEDIA_PAUSED, value);\n  }\n  /**\n   * Is the media loading\n   */\n  get mediaLoading() {\n    return getBooleanAttr(this, MediaUIAttributes.MEDIA_LOADING);\n  }\n  set mediaLoading(value) {\n    setBooleanAttr(this, MediaUIAttributes.MEDIA_LOADING, value);\n  }\n}\n_mediaController = new WeakMap();\n_delay = new WeakMap();\nif (!globalThis.customElements.get(\"media-loading-indicator\")) {\n  globalThis.customElements.define(\n    \"media-loading-indicator\",\n    MediaLoadingIndicator\n  );\n}\nvar media_loading_indicator_default = MediaLoadingIndicator;\nexport {\n  Attributes,\n  media_loading_indicator_default as default\n};\n", "import { MediaChromeButton } from \"./media-chrome-button.js\";\nimport { globalThis, document } from \"./utils/server-safe-globals.js\";\nimport { MediaUIEvents, MediaUIAttributes } from \"./constants.js\";\nimport { tooltipLabels, verbs } from \"./labels/labels.js\";\nimport { getStringAttr, setStringAttr } from \"./utils/element-utils.js\";\nconst { MEDIA_VOLUME_LEVEL } = MediaUIAttributes;\nconst offIcon = `<svg aria-hidden=\"true\" viewBox=\"0 0 24 24\">\n  <path d=\"M16.5 12A4.5 4.5 0 0 0 14 8v2.18l2.45 2.45a4.22 4.22 0 0 0 .05-.63Zm2.5 0a6.84 6.84 0 0 1-.54 2.64L20 16.15A8.8 8.8 0 0 0 21 12a9 9 0 0 0-7-8.77v2.06A7 7 0 0 1 19 12ZM4.27 3 3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25A6.92 6.92 0 0 1 14 18.7v2.06A9 9 0 0 0 17.69 19l2 2.05L21 19.73l-9-9L4.27 3ZM12 4 9.91 6.09 12 8.18V4Z\"/>\n</svg>`;\nconst lowIcon = `<svg aria-hidden=\"true\" viewBox=\"0 0 24 24\">\n  <path d=\"M3 9v6h4l5 5V4L7 9H3Zm13.5 3A4.5 4.5 0 0 0 14 8v8a4.47 4.47 0 0 0 2.5-4Z\"/>\n</svg>`;\nconst highIcon = `<svg aria-hidden=\"true\" viewBox=\"0 0 24 24\">\n  <path d=\"M3 9v6h4l5 5V4L7 9H3Zm13.5 3A4.5 4.5 0 0 0 14 8v8a4.47 4.47 0 0 0 2.5-4ZM14 3.23v2.06a7 7 0 0 1 0 13.42v2.06a9 9 0 0 0 0-17.54Z\"/>\n</svg>`;\nconst slotTemplate = document.createElement(\"template\");\nslotTemplate.innerHTML = /*html*/\n`\n  <style>\n  ${/* Default to High slot/icon. */\n\"\"}\n  :host(:not([${MEDIA_VOLUME_LEVEL}])) slot[name=icon] slot:not([name=high]), \n  :host([${MEDIA_VOLUME_LEVEL}=high]) slot[name=icon] slot:not([name=high]) {\n    display: none !important;\n  }\n\n  :host([${MEDIA_VOLUME_LEVEL}=off]) slot[name=icon] slot:not([name=off]) {\n    display: none !important;\n  }\n\n  :host([${MEDIA_VOLUME_LEVEL}=low]) slot[name=icon] slot:not([name=low]) {\n    display: none !important;\n  }\n\n  :host([${MEDIA_VOLUME_LEVEL}=medium]) slot[name=icon] slot:not([name=medium]) {\n    display: none !important;\n  }\n\n  :host(:not([${MEDIA_VOLUME_LEVEL}=off])) slot[name=tooltip-unmute],\n  :host([${MEDIA_VOLUME_LEVEL}=off]) slot[name=tooltip-mute] {\n    display: none;\n  }\n  </style>\n\n  <slot name=\"icon\">\n    <slot name=\"off\">${offIcon}</slot>\n    <slot name=\"low\">${lowIcon}</slot>\n    <slot name=\"medium\">${lowIcon}</slot>\n    <slot name=\"high\">${highIcon}</slot>\n  </slot>\n`;\nconst tooltipContent = (\n  /*html*/\n  `\n  <slot name=\"tooltip-mute\">${tooltipLabels.MUTE}</slot>\n  <slot name=\"tooltip-unmute\">${tooltipLabels.UNMUTE}</slot>\n`\n);\nconst updateAriaLabel = (el) => {\n  const muted = el.mediaVolumeLevel === \"off\";\n  const label = muted ? verbs.UNMUTE() : verbs.MUTE();\n  el.setAttribute(\"aria-label\", label);\n};\nclass MediaMuteButton extends MediaChromeButton {\n  static get observedAttributes() {\n    return [...super.observedAttributes, MediaUIAttributes.MEDIA_VOLUME_LEVEL];\n  }\n  constructor(options = {}) {\n    super({ slotTemplate, tooltipContent, ...options });\n  }\n  connectedCallback() {\n    updateAriaLabel(this);\n    super.connectedCallback();\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    if (attrName === MediaUIAttributes.MEDIA_VOLUME_LEVEL) {\n      updateAriaLabel(this);\n    }\n    super.attributeChangedCallback(attrName, oldValue, newValue);\n  }\n  /**\n   * @type {string | undefined}\n   */\n  get mediaVolumeLevel() {\n    return getStringAttr(this, MediaUIAttributes.MEDIA_VOLUME_LEVEL);\n  }\n  set mediaVolumeLevel(value) {\n    setStringAttr(this, MediaUIAttributes.MEDIA_VOLUME_LEVEL, value);\n  }\n  handleClick() {\n    const eventName = this.mediaVolumeLevel === \"off\" ? MediaUIEvents.MEDIA_UNMUTE_REQUEST : MediaUIEvents.MEDIA_MUTE_REQUEST;\n    this.dispatchEvent(\n      new globalThis.CustomEvent(eventName, { composed: true, bubbles: true })\n    );\n  }\n}\nif (!globalThis.customElements.get(\"media-mute-button\")) {\n  globalThis.customElements.define(\"media-mute-button\", MediaMuteButton);\n}\nvar media_mute_button_default = MediaMuteButton;\nexport {\n  media_mute_button_default as default\n};\n", "import { MediaChromeButton } from \"./media-chrome-button.js\";\nimport { globalThis, document } from \"./utils/server-safe-globals.js\";\nimport { MediaUIEvents, MediaUIAttributes } from \"./constants.js\";\nimport { tooltipLabels, verbs } from \"./labels/labels.js\";\nimport {\n  getBooleanAttr,\n  getStringAttr,\n  setBooleanAttr,\n  setStringAttr\n} from \"./utils/element-utils.js\";\nconst pipIcon = `<svg aria-hidden=\"true\" viewBox=\"0 0 28 24\">\n  <path d=\"M24 3H4a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h20a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1Zm-1 16H5V5h18v14Zm-3-8h-7v5h7v-5Z\"/>\n</svg>`;\nconst slotTemplate = document.createElement(\"template\");\nslotTemplate.innerHTML = /*html*/\n`\n  <style>\n  :host([${MediaUIAttributes.MEDIA_IS_PIP}]) slot[name=icon] slot:not([name=exit]) {\n    display: none !important;\n  }\n\n  ${/* Double negative, but safer if display doesn't equal 'block' */\n\"\"}\n  :host(:not([${MediaUIAttributes.MEDIA_IS_PIP}])) slot[name=icon] slot:not([name=enter]) {\n    display: none !important;\n  }\n\n  :host([${MediaUIAttributes.MEDIA_IS_PIP}]) slot[name=tooltip-enter],\n  :host(:not([${MediaUIAttributes.MEDIA_IS_PIP}])) slot[name=tooltip-exit] {\n    display: none;\n  }\n  </style>\n\n  <slot name=\"icon\">\n    <slot name=\"enter\">${pipIcon}</slot>\n    <slot name=\"exit\">${pipIcon}</slot>\n  </slot>\n`;\nconst tooltipContent = (\n  /*html*/\n  `\n  <slot name=\"tooltip-enter\">${tooltipLabels.ENTER_PIP}</slot>\n  <slot name=\"tooltip-exit\">${tooltipLabels.EXIT_PIP}</slot>\n`\n);\nconst updateAriaLabel = (el) => {\n  const label = el.mediaIsPip ? verbs.EXIT_PIP() : verbs.ENTER_PIP();\n  el.setAttribute(\"aria-label\", label);\n};\nclass MediaPipButton extends MediaChromeButton {\n  static get observedAttributes() {\n    return [\n      ...super.observedAttributes,\n      MediaUIAttributes.MEDIA_IS_PIP,\n      MediaUIAttributes.MEDIA_PIP_UNAVAILABLE\n    ];\n  }\n  constructor(options = {}) {\n    super({ slotTemplate, tooltipContent, ...options });\n  }\n  connectedCallback() {\n    updateAriaLabel(this);\n    super.connectedCallback();\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    if (attrName === MediaUIAttributes.MEDIA_IS_PIP) {\n      updateAriaLabel(this);\n    }\n    super.attributeChangedCallback(attrName, oldValue, newValue);\n  }\n  /**\n   * @type {string | undefined} Pip unavailability state\n   */\n  get mediaPipUnavailable() {\n    return getStringAttr(this, MediaUIAttributes.MEDIA_PIP_UNAVAILABLE);\n  }\n  set mediaPipUnavailable(value) {\n    setStringAttr(this, MediaUIAttributes.MEDIA_PIP_UNAVAILABLE, value);\n  }\n  /**\n   * @type {boolean} Is the media currently playing picture-in-picture\n   */\n  get mediaIsPip() {\n    return getBooleanAttr(this, MediaUIAttributes.MEDIA_IS_PIP);\n  }\n  set mediaIsPip(value) {\n    setBooleanAttr(this, MediaUIAttributes.MEDIA_IS_PIP, value);\n  }\n  handleClick() {\n    const eventName = this.mediaIsPip ? MediaUIEvents.MEDIA_EXIT_PIP_REQUEST : MediaUIEvents.MEDIA_ENTER_PIP_REQUEST;\n    this.dispatchEvent(\n      new globalThis.CustomEvent(eventName, { composed: true, bubbles: true })\n    );\n  }\n}\nif (!globalThis.customElements.get(\"media-pip-button\")) {\n  globalThis.customElements.define(\"media-pip-button\", MediaPipButton);\n}\nvar media_pip_button_default = MediaPipButton;\nexport {\n  media_pip_button_default as default\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar _rates;\nimport { MediaChromeButton } from \"./media-chrome-button.js\";\nimport { globalThis, document } from \"./utils/server-safe-globals.js\";\nimport { MediaUIEvents, MediaUIAttributes } from \"./constants.js\";\nimport { nouns, tooltipLabels } from \"./labels/labels.js\";\nimport { AttributeTokenList } from \"./utils/attribute-token-list.js\";\nimport { getNumericAttr, setNumericAttr } from \"./utils/element-utils.js\";\nconst Attributes = {\n  RATES: \"rates\"\n};\nconst DEFAULT_RATES = [1, 1.2, 1.5, 1.7, 2];\nconst DEFAULT_RATE = 1;\nconst slotTemplate = document.createElement(\"template\");\nslotTemplate.innerHTML = /*html*/\n`\n  <style>\n    :host {\n      min-width: 5ch;\n      padding: var(--media-button-padding, var(--media-control-padding, 10px 5px));\n    }\n  </style>\n  <slot name=\"icon\"></slot>\n`;\nclass MediaPlaybackRateButton extends MediaChromeButton {\n  constructor(options = {}) {\n    super({\n      slotTemplate,\n      tooltipContent: tooltipLabels.PLAYBACK_RATE,\n      ...options\n    });\n    __privateAdd(this, _rates, new AttributeTokenList(this, Attributes.RATES, {\n      defaultValue: DEFAULT_RATES\n    }));\n    this.container = this.shadowRoot.querySelector('slot[name=\"icon\"]');\n    this.container.innerHTML = `${DEFAULT_RATE}x`;\n  }\n  static get observedAttributes() {\n    return [\n      ...super.observedAttributes,\n      MediaUIAttributes.MEDIA_PLAYBACK_RATE,\n      Attributes.RATES\n    ];\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    super.attributeChangedCallback(attrName, oldValue, newValue);\n    if (attrName === Attributes.RATES) {\n      __privateGet(this, _rates).value = newValue;\n    }\n    if (attrName === MediaUIAttributes.MEDIA_PLAYBACK_RATE) {\n      const newPlaybackRate = newValue ? +newValue : Number.NaN;\n      const playbackRate = !Number.isNaN(newPlaybackRate) ? newPlaybackRate : DEFAULT_RATE;\n      this.container.innerHTML = `${playbackRate}x`;\n      this.setAttribute(\"aria-label\", nouns.PLAYBACK_RATE({ playbackRate }));\n    }\n  }\n  /**\n   * @type { AttributeTokenList | Array<number> | undefined} Will return a DOMTokenList.\n   * Setting a value will accept an array of numbers.\n   */\n  get rates() {\n    return __privateGet(this, _rates);\n  }\n  set rates(value) {\n    if (!value) {\n      __privateGet(this, _rates).value = \"\";\n    } else if (Array.isArray(value)) {\n      __privateGet(this, _rates).value = value.join(\" \");\n    }\n  }\n  /**\n   * @type {number} The current playback rate\n   */\n  get mediaPlaybackRate() {\n    return getNumericAttr(\n      this,\n      MediaUIAttributes.MEDIA_PLAYBACK_RATE,\n      DEFAULT_RATE\n    );\n  }\n  set mediaPlaybackRate(value) {\n    setNumericAttr(this, MediaUIAttributes.MEDIA_PLAYBACK_RATE, value);\n  }\n  handleClick() {\n    var _a, _b;\n    const availableRates = Array.from(this.rates.values(), (str) => +str).sort(\n      (a, b) => a - b\n    );\n    const detail = (_b = (_a = availableRates.find((r) => r > this.mediaPlaybackRate)) != null ? _a : availableRates[0]) != null ? _b : DEFAULT_RATE;\n    const evt = new globalThis.CustomEvent(\n      MediaUIEvents.MEDIA_PLAYBACK_RATE_REQUEST,\n      { composed: true, bubbles: true, detail }\n    );\n    this.dispatchEvent(evt);\n  }\n}\n_rates = new WeakMap();\nif (!globalThis.customElements.get(\"media-playback-rate-button\")) {\n  globalThis.customElements.define(\n    \"media-playback-rate-button\",\n    MediaPlaybackRateButton\n  );\n}\nvar media_playback_rate_button_default = MediaPlaybackRateButton;\nexport {\n  Attributes,\n  DEFAULT_RATE,\n  DEFAULT_RATES,\n  media_playback_rate_button_default as default\n};\n", "import { MediaChromeButton } from \"./media-chrome-button.js\";\nimport { globalThis, document } from \"./utils/server-safe-globals.js\";\nimport { MediaUIEvents, MediaUIAttributes } from \"./constants.js\";\nimport { tooltipLabels, verbs } from \"./labels/labels.js\";\nimport { getBooleanAttr, setBooleanAttr } from \"./utils/element-utils.js\";\nconst playIcon = `<svg aria-hidden=\"true\" viewBox=\"0 0 24 24\">\n  <path d=\"m6 21 15-9L6 3v18Z\"/>\n</svg>`;\nconst pauseIcon = `<svg aria-hidden=\"true\" viewBox=\"0 0 24 24\">\n  <path d=\"M6 20h4V4H6v16Zm8-16v16h4V4h-4Z\"/>\n</svg>`;\nconst slotTemplate = document.createElement(\"template\");\nslotTemplate.innerHTML = /*html*/\n`\n  <style>\n    :host([${MediaUIAttributes.MEDIA_PAUSED}]) slot[name=pause],\n    :host(:not([${MediaUIAttributes.MEDIA_PAUSED}])) slot[name=play] {\n      display: none !important;\n    }\n\n    :host([${MediaUIAttributes.MEDIA_PAUSED}]) slot[name=tooltip-pause],\n    :host(:not([${MediaUIAttributes.MEDIA_PAUSED}])) slot[name=tooltip-play] {\n      display: none;\n    }\n  </style>\n\n  <slot name=\"icon\">\n    <slot name=\"play\">${playIcon}</slot>\n    <slot name=\"pause\">${pauseIcon}</slot>\n  </slot>\n`;\nconst tooltipContent = (\n  /*html*/\n  `\n  <slot name=\"tooltip-play\">${tooltipLabels.PLAY}</slot>\n  <slot name=\"tooltip-pause\">${tooltipLabels.PAUSE}</slot>\n`\n);\nconst updateAriaLabel = (el) => {\n  const label = el.mediaPaused ? verbs.PLAY() : verbs.PAUSE();\n  el.setAttribute(\"aria-label\", label);\n};\nclass MediaPlayButton extends MediaChromeButton {\n  static get observedAttributes() {\n    return [\n      ...super.observedAttributes,\n      MediaUIAttributes.MEDIA_PAUSED,\n      MediaUIAttributes.MEDIA_ENDED\n    ];\n  }\n  constructor(options = {}) {\n    super({ slotTemplate, tooltipContent, ...options });\n  }\n  connectedCallback() {\n    updateAriaLabel(this);\n    super.connectedCallback();\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    if (attrName === MediaUIAttributes.MEDIA_PAUSED) {\n      updateAriaLabel(this);\n    }\n    super.attributeChangedCallback(attrName, oldValue, newValue);\n  }\n  /**\n   * Is the media paused\n   */\n  get mediaPaused() {\n    return getBooleanAttr(this, MediaUIAttributes.MEDIA_PAUSED);\n  }\n  set mediaPaused(value) {\n    setBooleanAttr(this, MediaUIAttributes.MEDIA_PAUSED, value);\n  }\n  handleClick() {\n    const eventName = this.mediaPaused ? MediaUIEvents.MEDIA_PLAY_REQUEST : MediaUIEvents.MEDIA_PAUSE_REQUEST;\n    this.dispatchEvent(\n      new globalThis.CustomEvent(eventName, { composed: true, bubbles: true })\n    );\n  }\n}\nif (!globalThis.customElements.get(\"media-play-button\")) {\n  globalThis.customElements.define(\"media-play-button\", MediaPlayButton);\n}\nvar media_play_button_default = MediaPlayButton;\nexport {\n  MediaPlayButton,\n  media_play_button_default as default\n};\n", "import { globalThis, document } from \"./utils/server-safe-globals.js\";\nimport { getStringAttr, setStringAttr } from \"./utils/element-utils.js\";\nconst Attributes = {\n  PLACEHOLDER_SRC: \"placeholdersrc\",\n  SRC: \"src\"\n};\nconst template = document.createElement(\"template\");\ntemplate.innerHTML = /*html*/\n`\n  <style>\n    :host {\n      pointer-events: none;\n      display: var(--media-poster-image-display, inline-block);\n      box-sizing: border-box;\n    }\n\n    img {\n      max-width: 100%;\n      max-height: 100%;\n      min-width: 100%;\n      min-height: 100%;\n      background-repeat: no-repeat;\n      background-position: var(--media-poster-image-background-position, var(--media-object-position, center));\n      background-size: var(--media-poster-image-background-size, var(--media-object-fit, contain));\n      object-fit: var(--media-object-fit, contain);\n      object-position: var(--media-object-position, center);\n    }\n  </style>\n\n  <img part=\"poster img\" aria-hidden=\"true\" id=\"image\"/>\n`;\nconst unsetBackgroundImage = (el) => {\n  el.style.removeProperty(\"background-image\");\n};\nconst setBackgroundImage = (el, image) => {\n  el.style[\"background-image\"] = `url('${image}')`;\n};\nclass MediaPosterImage extends globalThis.HTMLElement {\n  static get observedAttributes() {\n    return [Attributes.PLACEHOLDER_SRC, Attributes.SRC];\n  }\n  constructor() {\n    super();\n    if (!this.shadowRoot) {\n      this.attachShadow({ mode: \"open\" });\n      this.shadowRoot.appendChild(template.content.cloneNode(true));\n    }\n    this.image = this.shadowRoot.querySelector(\"#image\");\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    if (attrName === Attributes.SRC) {\n      if (newValue == null) {\n        this.image.removeAttribute(Attributes.SRC);\n      } else {\n        this.image.setAttribute(Attributes.SRC, newValue);\n      }\n    }\n    if (attrName === Attributes.PLACEHOLDER_SRC) {\n      if (newValue == null) {\n        unsetBackgroundImage(this.image);\n      } else {\n        setBackgroundImage(this.image, newValue);\n      }\n    }\n  }\n  /**\n   *\n   */\n  get placeholderSrc() {\n    return getStringAttr(this, Attributes.PLACEHOLDER_SRC);\n  }\n  set placeholderSrc(value) {\n    setStringAttr(this, Attributes.SRC, value);\n  }\n  /**\n   *\n   */\n  get src() {\n    return getStringAttr(this, Attributes.SRC);\n  }\n  set src(value) {\n    setStringAttr(this, Attributes.SRC, value);\n  }\n}\nif (!globalThis.customElements.get(\"media-poster-image\")) {\n  globalThis.customElements.define(\"media-poster-image\", MediaPosterImage);\n}\nvar media_poster_image_default = MediaPosterImage;\nexport {\n  Attributes,\n  media_poster_image_default as default\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar __privateSet = (obj, member, value, setter) => {\n  __accessCheck(obj, member, \"write to private field\");\n  setter ? setter.call(obj, value) : member.set(obj, value);\n  return value;\n};\nvar _slot;\nimport { MediaTextDisplay } from \"./media-text-display.js\";\nimport { globalThis } from \"./utils/server-safe-globals.js\";\nimport { MediaUIAttributes } from \"./constants.js\";\nimport { getStringAttr, setStringAttr } from \"./utils/element-utils.js\";\nclass MediaPreviewChapterDisplay extends MediaTextDisplay {\n  constructor() {\n    super();\n    __privateAdd(this, _slot, void 0);\n    __privateSet(this, _slot, this.shadowRoot.querySelector(\"slot\"));\n  }\n  static get observedAttributes() {\n    return [\n      ...super.observedAttributes,\n      MediaUIAttributes.MEDIA_PREVIEW_CHAPTER\n    ];\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    super.attributeChangedCallback(attrName, oldValue, newValue);\n    if (attrName === MediaUIAttributes.MEDIA_PREVIEW_CHAPTER) {\n      if (newValue !== oldValue && newValue != null) {\n        __privateGet(this, _slot).textContent = newValue;\n        if (newValue !== \"\") {\n          this.setAttribute(\"aria-valuetext\", `chapter: ${newValue}`);\n        } else {\n          this.removeAttribute(\"aria-valuetext\");\n        }\n      }\n    }\n  }\n  /**\n   * @type {string | undefined} Timeline preview chapter\n   */\n  get mediaPreviewChapter() {\n    return getStringAttr(this, MediaUIAttributes.MEDIA_PREVIEW_CHAPTER);\n  }\n  set mediaPreviewChapter(value) {\n    setStringAttr(this, MediaUIAttributes.MEDIA_PREVIEW_CHAPTER, value);\n  }\n}\n_slot = new WeakMap();\nif (!globalThis.customElements.get(\"media-preview-chapter-display\")) {\n  globalThis.customElements.define(\n    \"media-preview-chapter-display\",\n    MediaPreviewChapterDisplay\n  );\n}\nvar media_preview_chapter_display_default = MediaPreviewChapterDisplay;\nexport {\n  media_preview_chapter_display_default as default\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar __privateSet = (obj, member, value, setter) => {\n  __accessCheck(obj, member, \"write to private field\");\n  setter ? setter.call(obj, value) : member.set(obj, value);\n  return value;\n};\nvar _mediaController;\nimport { globalThis, document } from \"./utils/server-safe-globals.js\";\nimport {\n  MediaUIAttributes,\n  MediaStateReceiverAttributes\n} from \"./constants.js\";\nimport {\n  getOrInsertCSSRule,\n  getStringAttr,\n  setStringAttr\n} from \"./utils/element-utils.js\";\nconst template = document.createElement(\"template\");\ntemplate.innerHTML = /*html*/\n`\n  <style>\n    :host {\n      box-sizing: border-box;\n      display: var(--media-control-display, var(--media-preview-thumbnail-display, inline-block));\n      overflow: hidden;\n    }\n\n    img {\n      display: none;\n      position: relative;\n    }\n  </style>\n  <img crossorigin loading=\"eager\" decoding=\"async\">\n`;\nclass MediaPreviewThumbnail extends globalThis.HTMLElement {\n  constructor() {\n    super();\n    __privateAdd(this, _mediaController, void 0);\n    if (!this.shadowRoot) {\n      this.attachShadow({ mode: \"open\" });\n      this.shadowRoot.appendChild(template.content.cloneNode(true));\n    }\n  }\n  static get observedAttributes() {\n    return [\n      MediaStateReceiverAttributes.MEDIA_CONTROLLER,\n      MediaUIAttributes.MEDIA_PREVIEW_IMAGE,\n      MediaUIAttributes.MEDIA_PREVIEW_COORDS\n    ];\n  }\n  connectedCallback() {\n    var _a, _b, _c;\n    const mediaControllerId = this.getAttribute(\n      MediaStateReceiverAttributes.MEDIA_CONTROLLER\n    );\n    if (mediaControllerId) {\n      __privateSet(\n        this,\n        _mediaController,\n        // @ts-ignore\n        (_a = this.getRootNode()) == null ? void 0 : _a.getElementById(mediaControllerId)\n      );\n      (_c = (_b = __privateGet(this, _mediaController)) == null ? void 0 : _b.associateElement) == null ? void 0 : _c.call(_b, this);\n    }\n  }\n  disconnectedCallback() {\n    var _a, _b;\n    (_b = (_a = __privateGet(this, _mediaController)) == null ? void 0 : _a.unassociateElement) == null ? void 0 : _b.call(_a, this);\n    __privateSet(this, _mediaController, null);\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    var _a, _b, _c, _d, _e;\n    if ([\n      MediaUIAttributes.MEDIA_PREVIEW_IMAGE,\n      MediaUIAttributes.MEDIA_PREVIEW_COORDS\n    ].includes(attrName)) {\n      this.update();\n    }\n    if (attrName === MediaStateReceiverAttributes.MEDIA_CONTROLLER) {\n      if (oldValue) {\n        (_b = (_a = __privateGet(this, _mediaController)) == null ? void 0 : _a.unassociateElement) == null ? void 0 : _b.call(_a, this);\n        __privateSet(this, _mediaController, null);\n      }\n      if (newValue && this.isConnected) {\n        __privateSet(this, _mediaController, (_c = this.getRootNode()) == null ? void 0 : _c.getElementById(newValue));\n        (_e = (_d = __privateGet(this, _mediaController)) == null ? void 0 : _d.associateElement) == null ? void 0 : _e.call(_d, this);\n      }\n    }\n  }\n  /**\n   * @type {string | undefined} The url of the preview image\n   */\n  get mediaPreviewImage() {\n    return getStringAttr(this, MediaUIAttributes.MEDIA_PREVIEW_IMAGE);\n  }\n  set mediaPreviewImage(value) {\n    setStringAttr(this, MediaUIAttributes.MEDIA_PREVIEW_IMAGE, value);\n  }\n  /**\n   * @type {Array<number> | undefined} Fixed length array [x, y, width, height] or undefined\n   */\n  get mediaPreviewCoords() {\n    const attrVal = this.getAttribute(MediaUIAttributes.MEDIA_PREVIEW_COORDS);\n    if (!attrVal)\n      return void 0;\n    return attrVal.split(/\\s+/).map((coord) => +coord);\n  }\n  set mediaPreviewCoords(value) {\n    if (!value) {\n      this.removeAttribute(MediaUIAttributes.MEDIA_PREVIEW_COORDS);\n      return;\n    }\n    this.setAttribute(MediaUIAttributes.MEDIA_PREVIEW_COORDS, value.join(\" \"));\n  }\n  update() {\n    const coords = this.mediaPreviewCoords;\n    const previewImage = this.mediaPreviewImage;\n    if (!(coords && previewImage))\n      return;\n    const [x, y, w, h] = coords;\n    const src = previewImage.split(\"#\")[0];\n    const computedStyle = getComputedStyle(this);\n    const { maxWidth, maxHeight, minWidth, minHeight } = computedStyle;\n    const maxRatio = Math.min(parseInt(maxWidth) / w, parseInt(maxHeight) / h);\n    const minRatio = Math.max(parseInt(minWidth) / w, parseInt(minHeight) / h);\n    const isScalingDown = maxRatio < 1;\n    const scale = isScalingDown ? maxRatio : minRatio > 1 ? minRatio : 1;\n    const { style } = getOrInsertCSSRule(this.shadowRoot, \":host\");\n    const imgStyle = getOrInsertCSSRule(this.shadowRoot, \"img\").style;\n    const img = this.shadowRoot.querySelector(\"img\");\n    const extremum = isScalingDown ? \"min\" : \"max\";\n    style.setProperty(`${extremum}-width`, \"initial\", \"important\");\n    style.setProperty(`${extremum}-height`, \"initial\", \"important\");\n    style.width = `${w * scale}px`;\n    style.height = `${h * scale}px`;\n    const resize = () => {\n      imgStyle.width = `${this.imgWidth * scale}px`;\n      imgStyle.height = `${this.imgHeight * scale}px`;\n      imgStyle.display = \"block\";\n    };\n    if (img.src !== src) {\n      img.onload = () => {\n        this.imgWidth = img.naturalWidth;\n        this.imgHeight = img.naturalHeight;\n        resize();\n      };\n      img.src = src;\n      resize();\n    }\n    resize();\n    imgStyle.transform = `translate(-${x * scale}px, -${y * scale}px)`;\n  }\n}\n_mediaController = new WeakMap();\nif (!globalThis.customElements.get(\"media-preview-thumbnail\")) {\n  globalThis.customElements.define(\n    \"media-preview-thumbnail\",\n    MediaPreviewThumbnail\n  );\n}\nvar media_preview_thumbnail_default = MediaPreviewThumbnail;\nexport {\n  media_preview_thumbnail_default as default\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar __privateSet = (obj, member, value, setter) => {\n  __accessCheck(obj, member, \"write to private field\");\n  setter ? setter.call(obj, value) : member.set(obj, value);\n  return value;\n};\nvar _slot;\nimport { MediaTextDisplay } from \"./media-text-display.js\";\nimport { globalThis } from \"./utils/server-safe-globals.js\";\nimport { formatTime } from \"./utils/time.js\";\nimport { MediaUIAttributes } from \"./constants.js\";\nimport { getNumericAttr, setNumericAttr } from \"./utils/element-utils.js\";\nclass MediaPreviewTimeDisplay extends MediaTextDisplay {\n  constructor() {\n    super();\n    __privateAdd(this, _slot, void 0);\n    __privateSet(this, _slot, this.shadowRoot.querySelector(\"slot\"));\n    __privateGet(this, _slot).textContent = formatTime(0);\n  }\n  static get observedAttributes() {\n    return [...super.observedAttributes, MediaUIAttributes.MEDIA_PREVIEW_TIME];\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    super.attributeChangedCallback(attrName, oldValue, newValue);\n    if (attrName === MediaUIAttributes.MEDIA_PREVIEW_TIME && newValue != null) {\n      __privateGet(this, _slot).textContent = formatTime(parseFloat(newValue));\n    }\n  }\n  /**\n   * Timeline preview time\n   */\n  get mediaPreviewTime() {\n    return getNumericAttr(this, MediaUIAttributes.MEDIA_PREVIEW_TIME);\n  }\n  set mediaPreviewTime(value) {\n    setNumericAttr(this, MediaUIAttributes.MEDIA_PREVIEW_TIME, value);\n  }\n}\n_slot = new WeakMap();\nif (!globalThis.customElements.get(\"media-preview-time-display\")) {\n  globalThis.customElements.define(\n    \"media-preview-time-display\",\n    MediaPreviewTimeDisplay\n  );\n}\nvar media_preview_time_display_default = MediaPreviewTimeDisplay;\nexport {\n  media_preview_time_display_default as default\n};\n", "import { MediaChromeButton } from \"./media-chrome-button.js\";\nimport { globalThis, document } from \"./utils/server-safe-globals.js\";\nimport { MediaUIEvents, MediaUIAttributes } from \"./constants.js\";\nimport { getNumericAttr, setNumericAttr } from \"./utils/element-utils.js\";\nimport { tooltipLabels, verbs } from \"./labels/labels.js\";\nimport { getSlotted, updateIconText } from \"./utils/element-utils.js\";\nconst Attributes = {\n  SEEK_OFFSET: \"seekoffset\"\n};\nconst DEFAULT_SEEK_OFFSET = 30;\nconst backwardIcon = `<svg aria-hidden=\"true\" viewBox=\"0 0 20 24\"><defs><style>.text{font-size:8px;font-family:Arial-BoldMT, Arial;font-weight:700;}</style></defs><text class=\"text value\" transform=\"translate(2.18 19.87)\">${DEFAULT_SEEK_OFFSET}</text><path d=\"M10 6V3L4.37 7 10 10.94V8a5.54 5.54 0 0 1 1.9 10.48v2.12A7.5 7.5 0 0 0 10 6Z\"/></svg>`;\nconst slotTemplate = document.createElement(\"template\");\nslotTemplate.innerHTML = `\n  <slot name=\"icon\">${backwardIcon}</slot>\n`;\nconst DEFAULT_TIME = 0;\nclass MediaSeekBackwardButton extends MediaChromeButton {\n  static get observedAttributes() {\n    return [\n      ...super.observedAttributes,\n      MediaUIAttributes.MEDIA_CURRENT_TIME,\n      Attributes.SEEK_OFFSET\n    ];\n  }\n  constructor(options = {}) {\n    super({\n      slotTemplate,\n      tooltipContent: tooltipLabels.SEEK_BACKWARD,\n      ...options\n    });\n  }\n  connectedCallback() {\n    this.seekOffset = getNumericAttr(\n      this,\n      Attributes.SEEK_OFFSET,\n      DEFAULT_SEEK_OFFSET\n    );\n    super.connectedCallback();\n  }\n  attributeChangedCallback(attrName, _oldValue, newValue) {\n    if (attrName === Attributes.SEEK_OFFSET) {\n      this.seekOffset = getNumericAttr(\n        this,\n        Attributes.SEEK_OFFSET,\n        DEFAULT_SEEK_OFFSET\n      );\n    }\n    super.attributeChangedCallback(attrName, _oldValue, newValue);\n  }\n  // Own props\n  /**\n   * Seek amount in seconds\n   */\n  get seekOffset() {\n    return getNumericAttr(this, Attributes.SEEK_OFFSET, DEFAULT_SEEK_OFFSET);\n  }\n  set seekOffset(value) {\n    setNumericAttr(this, Attributes.SEEK_OFFSET, value);\n    this.setAttribute(\n      \"aria-label\",\n      verbs.SEEK_BACK_N_SECS({ seekOffset: this.seekOffset })\n    );\n    updateIconText(getSlotted(this, \"icon\"), this.seekOffset);\n  }\n  // Props derived from Media UI Attributes\n  /**\n   * The current time in seconds\n   */\n  get mediaCurrentTime() {\n    return getNumericAttr(\n      this,\n      MediaUIAttributes.MEDIA_CURRENT_TIME,\n      DEFAULT_TIME\n    );\n  }\n  set mediaCurrentTime(time) {\n    setNumericAttr(this, MediaUIAttributes.MEDIA_CURRENT_TIME, time);\n  }\n  handleClick() {\n    const detail = Math.max(this.mediaCurrentTime - this.seekOffset, 0);\n    const evt = new globalThis.CustomEvent(MediaUIEvents.MEDIA_SEEK_REQUEST, {\n      composed: true,\n      bubbles: true,\n      detail\n    });\n    this.dispatchEvent(evt);\n  }\n}\nif (!globalThis.customElements.get(\"media-seek-backward-button\")) {\n  globalThis.customElements.define(\n    \"media-seek-backward-button\",\n    MediaSeekBackwardButton\n  );\n}\nvar media_seek_backward_button_default = MediaSeekBackwardButton;\nexport {\n  Attributes,\n  media_seek_backward_button_default as default\n};\n", "import { MediaChromeButton } from \"./media-chrome-button.js\";\nimport { globalThis, document } from \"./utils/server-safe-globals.js\";\nimport { MediaUIEvents, MediaUIAttributes } from \"./constants.js\";\nimport { getNumericAttr, setNumericAttr } from \"./utils/element-utils.js\";\nimport { tooltipLabels, verbs } from \"./labels/labels.js\";\nimport { getSlotted, updateIconText } from \"./utils/element-utils.js\";\nconst Attributes = {\n  SEEK_OFFSET: \"seekoffset\"\n};\nconst DEFAULT_SEEK_OFFSET = 30;\nconst forwardIcon = `<svg aria-hidden=\"true\" viewBox=\"0 0 20 24\"><defs><style>.text{font-size:8px;font-family:Arial-BoldMT, Arial;font-weight:700;}</style></defs><text class=\"text value\" transform=\"translate(8.9 19.87)\">${DEFAULT_SEEK_OFFSET}</text><path d=\"M10 6V3l5.61 4L10 10.94V8a5.54 5.54 0 0 0-1.9 10.48v2.12A7.5 7.5 0 0 1 10 6Z\"/></svg>`;\nconst slotTemplate = document.createElement(\"template\");\nslotTemplate.innerHTML = `\n  <slot name=\"icon\">${forwardIcon}</slot>\n`;\nconst DEFAULT_TIME = 0;\nclass MediaSeekForwardButton extends MediaChromeButton {\n  static get observedAttributes() {\n    return [\n      ...super.observedAttributes,\n      MediaUIAttributes.MEDIA_CURRENT_TIME,\n      Attributes.SEEK_OFFSET\n    ];\n  }\n  constructor(options = {}) {\n    super({\n      slotTemplate,\n      tooltipContent: tooltipLabels.SEEK_FORWARD,\n      ...options\n    });\n  }\n  connectedCallback() {\n    this.seekOffset = getNumericAttr(\n      this,\n      Attributes.SEEK_OFFSET,\n      DEFAULT_SEEK_OFFSET\n    );\n    super.connectedCallback();\n  }\n  attributeChangedCallback(attrName, _oldValue, newValue) {\n    if (attrName === Attributes.SEEK_OFFSET) {\n      this.seekOffset = getNumericAttr(\n        this,\n        Attributes.SEEK_OFFSET,\n        DEFAULT_SEEK_OFFSET\n      );\n    }\n    super.attributeChangedCallback(attrName, _oldValue, newValue);\n  }\n  // Own props\n  /**\n   * Seek amount in seconds\n   */\n  get seekOffset() {\n    return getNumericAttr(this, Attributes.SEEK_OFFSET, DEFAULT_SEEK_OFFSET);\n  }\n  set seekOffset(value) {\n    setNumericAttr(this, Attributes.SEEK_OFFSET, value);\n    this.setAttribute(\n      \"aria-label\",\n      verbs.SEEK_FORWARD_N_SECS({ seekOffset: this.seekOffset })\n    );\n    updateIconText(getSlotted(this, \"icon\"), this.seekOffset);\n  }\n  // Props derived from Media UI Attributes\n  /**\n   * The current time in seconds\n   */\n  get mediaCurrentTime() {\n    return getNumericAttr(\n      this,\n      MediaUIAttributes.MEDIA_CURRENT_TIME,\n      DEFAULT_TIME\n    );\n  }\n  set mediaCurrentTime(time) {\n    setNumericAttr(this, MediaUIAttributes.MEDIA_CURRENT_TIME, time);\n  }\n  handleClick() {\n    const detail = this.mediaCurrentTime + this.seekOffset;\n    const evt = new globalThis.CustomEvent(MediaUIEvents.MEDIA_SEEK_REQUEST, {\n      composed: true,\n      bubbles: true,\n      detail\n    });\n    this.dispatchEvent(evt);\n  }\n}\nif (!globalThis.customElements.get(\"media-seek-forward-button\")) {\n  globalThis.customElements.define(\n    \"media-seek-forward-button\",\n    MediaSeekForwardButton\n  );\n}\nvar media_seek_forward_button_default = MediaSeekForwardButton;\nexport {\n  Attributes,\n  media_seek_forward_button_default as default\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar __privateSet = (obj, member, value, setter) => {\n  __accessCheck(obj, member, \"write to private field\");\n  setter ? setter.call(obj, value) : member.set(obj, value);\n  return value;\n};\nvar _slot;\nimport { MediaTextDisplay } from \"./media-text-display.js\";\nimport {\n  getBooleanAttr,\n  getNumericAttr,\n  getOrInsertCSSRule,\n  setBooleanAttr,\n  setNumericAttr\n} from \"./utils/element-utils.js\";\nimport { globalThis } from \"./utils/server-safe-globals.js\";\nimport { formatAsTimePhrase, formatTime } from \"./utils/time.js\";\nimport { MediaUIAttributes } from \"./constants.js\";\nimport { nouns } from \"./labels/labels.js\";\nconst Attributes = {\n  REMAINING: \"remaining\",\n  SHOW_DURATION: \"showduration\",\n  NO_TOGGLE: \"notoggle\"\n};\nconst CombinedAttributes = [\n  ...Object.values(Attributes),\n  MediaUIAttributes.MEDIA_CURRENT_TIME,\n  MediaUIAttributes.MEDIA_DURATION,\n  MediaUIAttributes.MEDIA_SEEKABLE\n];\nconst ButtonPressedKeys = [\"Enter\", \" \"];\nconst DEFAULT_TIMES_SEP = \"&nbsp;/&nbsp;\";\nconst formatTimesLabel = (el, { timesSep = DEFAULT_TIMES_SEP } = {}) => {\n  var _a, _b;\n  const showRemaining = el.hasAttribute(Attributes.REMAINING);\n  const showDuration = el.hasAttribute(Attributes.SHOW_DURATION);\n  const currentTime = (_a = el.mediaCurrentTime) != null ? _a : 0;\n  const [, seekableEnd] = (_b = el.mediaSeekable) != null ? _b : [];\n  let endTime = 0;\n  if (Number.isFinite(el.mediaDuration)) {\n    endTime = el.mediaDuration;\n  } else if (Number.isFinite(seekableEnd)) {\n    endTime = seekableEnd;\n  }\n  const timeLabel = showRemaining ? formatTime(0 - (endTime - currentTime)) : formatTime(currentTime);\n  if (!showDuration)\n    return timeLabel;\n  return `${timeLabel}${timesSep}${formatTime(endTime)}`;\n};\nconst DEFAULT_MISSING_TIME_PHRASE = \"video not loaded, unknown time.\";\nconst updateAriaValueText = (el) => {\n  var _a;\n  const currentTime = el.mediaCurrentTime;\n  const [, seekableEnd] = (_a = el.mediaSeekable) != null ? _a : [];\n  let endTime = null;\n  if (Number.isFinite(el.mediaDuration)) {\n    endTime = el.mediaDuration;\n  } else if (Number.isFinite(seekableEnd)) {\n    endTime = seekableEnd;\n  }\n  if (currentTime == null || endTime === null) {\n    el.setAttribute(\"aria-valuetext\", DEFAULT_MISSING_TIME_PHRASE);\n    return;\n  }\n  const showRemaining = el.hasAttribute(Attributes.REMAINING);\n  const showDuration = el.hasAttribute(Attributes.SHOW_DURATION);\n  const currentTimePhrase = showRemaining ? formatAsTimePhrase(0 - (endTime - currentTime)) : formatAsTimePhrase(currentTime);\n  if (!showDuration) {\n    el.setAttribute(\"aria-valuetext\", currentTimePhrase);\n    return;\n  }\n  const totalTimePhrase = formatAsTimePhrase(endTime);\n  const fullPhrase = `${currentTimePhrase} of ${totalTimePhrase}`;\n  el.setAttribute(\"aria-valuetext\", fullPhrase);\n};\nclass MediaTimeDisplay extends MediaTextDisplay {\n  constructor() {\n    super();\n    __privateAdd(this, _slot, void 0);\n    __privateSet(this, _slot, this.shadowRoot.querySelector(\"slot\"));\n    __privateGet(this, _slot).innerHTML = `${formatTimesLabel(this)}`;\n  }\n  static get observedAttributes() {\n    return [...super.observedAttributes, ...CombinedAttributes, \"disabled\"];\n  }\n  connectedCallback() {\n    const { style } = getOrInsertCSSRule(\n      this.shadowRoot,\n      \":host(:hover:not([notoggle]))\"\n    );\n    style.setProperty(\"cursor\", \"pointer\");\n    style.setProperty(\n      \"background\",\n      \"var(--media-control-hover-background, rgba(50 50 70 / .7))\"\n    );\n    if (!this.hasAttribute(\"disabled\")) {\n      this.enable();\n    }\n    this.setAttribute(\"role\", \"progressbar\");\n    this.setAttribute(\"aria-label\", nouns.PLAYBACK_TIME());\n    const keyUpHandler = (evt) => {\n      const { key } = evt;\n      if (!ButtonPressedKeys.includes(key)) {\n        this.removeEventListener(\"keyup\", keyUpHandler);\n        return;\n      }\n      this.toggleTimeDisplay();\n    };\n    this.addEventListener(\"keydown\", (evt) => {\n      const { metaKey, altKey, key } = evt;\n      if (metaKey || altKey || !ButtonPressedKeys.includes(key)) {\n        this.removeEventListener(\"keyup\", keyUpHandler);\n        return;\n      }\n      this.addEventListener(\"keyup\", keyUpHandler);\n    });\n    this.addEventListener(\"click\", this.toggleTimeDisplay);\n    super.connectedCallback();\n  }\n  toggleTimeDisplay() {\n    if (this.noToggle) {\n      return;\n    }\n    if (this.hasAttribute(\"remaining\")) {\n      this.removeAttribute(\"remaining\");\n    } else {\n      this.setAttribute(\"remaining\", \"\");\n    }\n  }\n  disconnectedCallback() {\n    this.disable();\n    super.disconnectedCallback();\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    if (CombinedAttributes.includes(attrName)) {\n      this.update();\n    } else if (attrName === \"disabled\" && newValue !== oldValue) {\n      if (newValue == null) {\n        this.enable();\n      } else {\n        this.disable();\n      }\n    }\n    super.attributeChangedCallback(attrName, oldValue, newValue);\n  }\n  enable() {\n    this.tabIndex = 0;\n  }\n  disable() {\n    this.tabIndex = -1;\n  }\n  // Own props\n  /**\n   * Whether to show the remaining time\n   */\n  get remaining() {\n    return getBooleanAttr(this, Attributes.REMAINING);\n  }\n  set remaining(show) {\n    setBooleanAttr(this, Attributes.REMAINING, show);\n  }\n  /**\n   * Whether to show the duration\n   */\n  get showDuration() {\n    return getBooleanAttr(this, Attributes.SHOW_DURATION);\n  }\n  set showDuration(show) {\n    setBooleanAttr(this, Attributes.SHOW_DURATION, show);\n  }\n  /**\n   * Disable the default behavior that toggles between current and remaining time\n   */\n  get noToggle() {\n    return getBooleanAttr(this, Attributes.NO_TOGGLE);\n  }\n  set noToggle(noToggle) {\n    setBooleanAttr(this, Attributes.NO_TOGGLE, noToggle);\n  }\n  // Props derived from media UI attributes\n  /**\n   * Get the duration\n   */\n  get mediaDuration() {\n    return getNumericAttr(this, MediaUIAttributes.MEDIA_DURATION);\n  }\n  set mediaDuration(time) {\n    setNumericAttr(this, MediaUIAttributes.MEDIA_DURATION, time);\n  }\n  /**\n   * The current time in seconds\n   */\n  get mediaCurrentTime() {\n    return getNumericAttr(this, MediaUIAttributes.MEDIA_CURRENT_TIME);\n  }\n  set mediaCurrentTime(time) {\n    setNumericAttr(this, MediaUIAttributes.MEDIA_CURRENT_TIME, time);\n  }\n  /**\n   * Range of values that can be seeked to.\n   * An array of two numbers [start, end]\n   */\n  get mediaSeekable() {\n    const seekable = this.getAttribute(MediaUIAttributes.MEDIA_SEEKABLE);\n    if (!seekable)\n      return void 0;\n    return seekable.split(\":\").map((time) => +time);\n  }\n  set mediaSeekable(range) {\n    if (range == null) {\n      this.removeAttribute(MediaUIAttributes.MEDIA_SEEKABLE);\n      return;\n    }\n    this.setAttribute(MediaUIAttributes.MEDIA_SEEKABLE, range.join(\":\"));\n  }\n  update() {\n    const timesLabel = formatTimesLabel(this);\n    updateAriaValueText(this);\n    if (timesLabel !== __privateGet(this, _slot).innerHTML) {\n      __privateGet(this, _slot).innerHTML = timesLabel;\n    }\n  }\n}\n_slot = new WeakMap();\nif (!globalThis.customElements.get(\"media-time-display\")) {\n  globalThis.customElements.define(\"media-time-display\", MediaTimeDisplay);\n}\nvar media_time_display_default = MediaTimeDisplay;\nexport {\n  Attributes,\n  media_time_display_default as default\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar __privateSet = (obj, member, value, setter) => {\n  __accessCheck(obj, member, \"write to private field\");\n  setter ? setter.call(obj, value) : member.set(obj, value);\n  return value;\n};\nvar __privateWrapper = (obj, member, setter, getter) => ({\n  set _(value) {\n    __privateSet(obj, member, value, setter);\n  },\n  get _() {\n    return __privateGet(obj, member, getter);\n  }\n});\nvar _range, _startTime, _previousTime, _deltaTime, _frameCount, _updateTimestamp, _updateStartValue, _lastRangeIncrease, _id, _animate;\nclass RangeAnimation {\n  constructor(range, callback, fps) {\n    __privateAdd(this, _range, void 0);\n    __privateAdd(this, _startTime, void 0);\n    __privateAdd(this, _previousTime, void 0);\n    __privateAdd(this, _deltaTime, void 0);\n    __privateAdd(this, _frameCount, void 0);\n    __privateAdd(this, _updateTimestamp, void 0);\n    __privateAdd(this, _updateStartValue, void 0);\n    __privateAdd(this, _lastRangeIncrease, void 0);\n    __privateAdd(this, _id, 0);\n    __privateAdd(this, _animate, (now = performance.now()) => {\n      __privateSet(this, _id, requestAnimationFrame(__privateGet(this, _animate)));\n      __privateSet(this, _deltaTime, performance.now() - __privateGet(this, _previousTime));\n      const fpsInterval = 1e3 / this.fps;\n      if (__privateGet(this, _deltaTime) > fpsInterval) {\n        __privateSet(this, _previousTime, now - __privateGet(this, _deltaTime) % fpsInterval);\n        const fps = 1e3 / ((now - __privateGet(this, _startTime)) / ++__privateWrapper(this, _frameCount)._);\n        const delta = (now - __privateGet(this, _updateTimestamp)) / 1e3 / this.duration;\n        let value = __privateGet(this, _updateStartValue) + delta * this.playbackRate;\n        const increase = value - __privateGet(this, _range).valueAsNumber;\n        if (increase > 0) {\n          __privateSet(this, _lastRangeIncrease, this.playbackRate / this.duration / fps);\n        } else {\n          __privateSet(this, _lastRangeIncrease, 0.995 * __privateGet(this, _lastRangeIncrease));\n          value = __privateGet(this, _range).valueAsNumber + __privateGet(this, _lastRangeIncrease);\n        }\n        this.callback(value);\n      }\n    });\n    __privateSet(this, _range, range);\n    this.callback = callback;\n    this.fps = fps;\n  }\n  start() {\n    if (__privateGet(this, _id) !== 0)\n      return;\n    __privateSet(this, _previousTime, performance.now());\n    __privateSet(this, _startTime, __privateGet(this, _previousTime));\n    __privateSet(this, _frameCount, 0);\n    __privateGet(this, _animate).call(this);\n  }\n  stop() {\n    if (__privateGet(this, _id) === 0)\n      return;\n    cancelAnimationFrame(__privateGet(this, _id));\n    __privateSet(this, _id, 0);\n  }\n  update({ start, duration, playbackRate }) {\n    const increase = start - __privateGet(this, _range).valueAsNumber;\n    const durationDelta = Math.abs(duration - this.duration);\n    if (increase > 0 || increase < -0.03 || durationDelta >= 0.5) {\n      this.callback(start);\n    }\n    __privateSet(this, _updateStartValue, start);\n    __privateSet(this, _updateTimestamp, performance.now());\n    this.duration = duration;\n    this.playbackRate = playbackRate;\n  }\n}\n_range = new WeakMap();\n_startTime = new WeakMap();\n_previousTime = new WeakMap();\n_deltaTime = new WeakMap();\n_frameCount = new WeakMap();\n_updateTimestamp = new WeakMap();\n_updateStartValue = new WeakMap();\n_lastRangeIncrease = new WeakMap();\n_id = new WeakMap();\n_animate = new WeakMap();\nexport {\n  RangeAnimation\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar __privateSet = (obj, member, value, setter) => {\n  __accessCheck(obj, member, \"write to private field\");\n  setter ? setter.call(obj, value) : member.set(obj, value);\n  return value;\n};\nvar __privateMethod = (obj, member, method) => {\n  __accessCheck(obj, member, \"access private method\");\n  return method;\n};\nvar _rootNode, _animation, _boxes, _previewTime, _previewBox, _currentBox, _boxPaddingLeft, _boxPaddingRight, _mediaChaptersCues, _toggleRangeAnimation, toggleRangeAnimation_fn, _shouldRangeAnimate, shouldRangeAnimate_fn, _updateRange, _getElementRects, getElementRects_fn, _getBoxPosition, getBoxPosition_fn, _getBoxShiftPosition, getBoxShiftPosition_fn, _handlePointerMove, handlePointerMove_fn, _previewRequest, previewRequest_fn, _seekRequest, seekRequest_fn;\nimport { globalThis, document } from \"./utils/server-safe-globals.js\";\nimport { MediaChromeRange } from \"./media-chrome-range.js\";\nimport \"./media-preview-thumbnail.js\";\nimport \"./media-preview-time-display.js\";\nimport \"./media-preview-chapter-display.js\";\nimport { MediaUIEvents, MediaUIAttributes } from \"./constants.js\";\nimport { nouns } from \"./labels/labels.js\";\nimport { isValidNumber } from \"./utils/utils.js\";\nimport { formatAsTimePhrase } from \"./utils/time.js\";\nimport { isElementVisible } from \"./utils/element-utils.js\";\nimport { RangeAnimation } from \"./utils/range-animation.js\";\nimport {\n  getOrInsertCSSRule,\n  containsComposedNode,\n  closestComposedNode,\n  getBooleanAttr,\n  setBooleanAttr,\n  getNumericAttr,\n  setNumericAttr,\n  getStringAttr,\n  setStringAttr\n} from \"./utils/element-utils.js\";\nconst DEFAULT_MISSING_TIME_PHRASE = \"video not loaded, unknown time.\";\nconst updateAriaValueText = (el) => {\n  const range = el.range;\n  const currentTimePhrase = formatAsTimePhrase(+calcTimeFromRangeValue(el));\n  const totalTimePhrase = formatAsTimePhrase(+el.mediaSeekableEnd);\n  const fullPhrase = !(currentTimePhrase && totalTimePhrase) ? DEFAULT_MISSING_TIME_PHRASE : `${currentTimePhrase} of ${totalTimePhrase}`;\n  range.setAttribute(\"aria-valuetext\", fullPhrase);\n};\nconst template = document.createElement(\"template\");\ntemplate.innerHTML = /*html*/\n`\n  <style>\n    :host {\n      --media-box-border-radius: 4px;\n      --media-box-padding-left: 10px;\n      --media-box-padding-right: 10px;\n      --media-preview-border-radius: var(--media-box-border-radius);\n      --media-box-arrow-offset: var(--media-box-border-radius);\n      --_control-background: var(--media-control-background, var(--media-secondary-color, rgb(20 20 30 / .7)));\n      --_preview-background: var(--media-preview-background, var(--_control-background));\n\n      ${/* 1% rail width trick was off in Safari, contain: layout seems to\nprevent the horizontal overflow as well. */\n\"\"}\n      contain: layout;\n    }\n\n    #buffered {\n      background: var(--media-time-range-buffered-color, rgb(255 255 255 / .4));\n      position: absolute;\n      height: 100%;\n      will-change: width;\n    }\n\n    #preview-rail,\n    #current-rail {\n      width: 100%;\n      position: absolute;\n      left: 0;\n      bottom: 100%;\n      pointer-events: none;\n      will-change: transform;\n    }\n\n    [part~=\"box\"] {\n      width: min-content;\n      ${/* absolute position is needed here so the box doesn't overflow the bounds */\n\"\"}\n      position: absolute;\n      bottom: 100%;\n      flex-direction: column;\n      align-items: center;\n      transform: translateX(-50%);\n    }\n\n    [part~=\"current-box\"] {\n      display: var(--media-current-box-display, var(--media-box-display, flex));\n      margin: var(--media-current-box-margin, var(--media-box-margin, 0 0 5px));\n      visibility: hidden;\n    }\n\n    [part~=\"preview-box\"] {\n      display: var(--media-preview-box-display, var(--media-box-display, flex));\n      margin: var(--media-preview-box-margin, var(--media-box-margin, 0 0 5px));\n      transition-property: var(--media-preview-transition-property, visibility, opacity);\n      transition-duration: var(--media-preview-transition-duration-out, .25s);\n      transition-delay: var(--media-preview-transition-delay-out, 0s);\n      visibility: hidden;\n      opacity: 0;\n    }\n\n    :host(:is([${MediaUIAttributes.MEDIA_PREVIEW_IMAGE}], [${MediaUIAttributes.MEDIA_PREVIEW_TIME}])[dragging]) [part~=\"preview-box\"] {\n      transition-duration: var(--media-preview-transition-duration-in, .5s);\n      transition-delay: var(--media-preview-transition-delay-in, .25s);\n      visibility: visible;\n      opacity: 1;\n    }\n\n    @media (hover: hover) {\n      :host(:is([${MediaUIAttributes.MEDIA_PREVIEW_IMAGE}], [${MediaUIAttributes.MEDIA_PREVIEW_TIME}]):hover) [part~=\"preview-box\"] {\n        transition-duration: var(--media-preview-transition-duration-in, .5s);\n        transition-delay: var(--media-preview-transition-delay-in, .25s);\n        visibility: visible;\n        opacity: 1;\n      }\n    }\n\n    media-preview-thumbnail,\n    ::slotted(media-preview-thumbnail) {\n      visibility: hidden;\n      ${/* delay changing these CSS props until the preview box transition is ended */\n\"\"}\n      transition: visibility 0s .25s;\n      transition-delay: calc(var(--media-preview-transition-delay-out, 0s) + var(--media-preview-transition-duration-out, .25s));\n      background: var(--media-preview-thumbnail-background, var(--_preview-background));\n      box-shadow: var(--media-preview-thumbnail-box-shadow, 0 0 4px rgb(0 0 0 / .2));\n      max-width: var(--media-preview-thumbnail-max-width, 180px);\n      max-height: var(--media-preview-thumbnail-max-height, 160px);\n      min-width: var(--media-preview-thumbnail-min-width, 120px);\n      min-height: var(--media-preview-thumbnail-min-height, 80px);\n      border: var(--media-preview-thumbnail-border);\n      border-radius: var(--media-preview-thumbnail-border-radius,\n        var(--media-preview-border-radius) var(--media-preview-border-radius) 0 0);\n    }\n\n    :host([${MediaUIAttributes.MEDIA_PREVIEW_IMAGE}][dragging]) media-preview-thumbnail,\n    :host([${MediaUIAttributes.MEDIA_PREVIEW_IMAGE}][dragging]) ::slotted(media-preview-thumbnail) {\n      transition-delay: var(--media-preview-transition-delay-in, .25s);\n      visibility: visible;\n    }\n\n    @media (hover: hover) {\n      :host([${MediaUIAttributes.MEDIA_PREVIEW_IMAGE}]:hover) media-preview-thumbnail,\n      :host([${MediaUIAttributes.MEDIA_PREVIEW_IMAGE}]:hover) ::slotted(media-preview-thumbnail) {\n        transition-delay: var(--media-preview-transition-delay-in, .25s);\n        visibility: visible;\n      }\n\n      :host([${MediaUIAttributes.MEDIA_PREVIEW_TIME}]:hover) {\n        --media-time-range-hover-display: block;\n      }\n    }\n\n    media-preview-chapter-display,\n    ::slotted(media-preview-chapter-display) {\n      font-size: var(--media-font-size, 13px);\n      line-height: 17px;\n      min-width: 0;\n      visibility: hidden;\n      ${/* delay changing these CSS props until the preview box transition is ended */\n\"\"}\n      transition: min-width 0s, border-radius 0s, margin 0s, padding 0s, visibility 0s;\n      transition-delay: calc(var(--media-preview-transition-delay-out, 0s) + var(--media-preview-transition-duration-out, .25s));\n      background: var(--media-preview-chapter-background, var(--_preview-background));\n      border-radius: var(--media-preview-chapter-border-radius,\n        var(--media-preview-border-radius) var(--media-preview-border-radius)\n        var(--media-preview-border-radius) var(--media-preview-border-radius));\n      padding: var(--media-preview-chapter-padding, 3.5px 9px);\n      margin: var(--media-preview-chapter-margin, 0 0 5px);\n      text-shadow: var(--media-preview-chapter-text-shadow, 0 0 4px rgb(0 0 0 / .75));\n    }\n\n    :host([${MediaUIAttributes.MEDIA_PREVIEW_IMAGE}]) media-preview-chapter-display,\n    :host([${MediaUIAttributes.MEDIA_PREVIEW_IMAGE}]) ::slotted(media-preview-chapter-display) {\n      transition-delay: var(--media-preview-transition-delay-in, .25s);\n      border-radius: var(--media-preview-chapter-border-radius, 0);\n      padding: var(--media-preview-chapter-padding, 3.5px 9px 0);\n      margin: var(--media-preview-chapter-margin, 0);\n      min-width: 100%;\n    }\n\n    media-preview-chapter-display[${MediaUIAttributes.MEDIA_PREVIEW_CHAPTER}],\n    ::slotted(media-preview-chapter-display[${MediaUIAttributes.MEDIA_PREVIEW_CHAPTER}]) {\n      visibility: visible;\n    }\n\n    media-preview-chapter-display:not([aria-valuetext]),\n    ::slotted(media-preview-chapter-display:not([aria-valuetext])) {\n      display: none;\n    }\n\n    media-preview-time-display,\n    ::slotted(media-preview-time-display),\n    media-time-display,\n    ::slotted(media-time-display) {\n      font-size: var(--media-font-size, 13px);\n      line-height: 17px;\n      min-width: 0;\n      ${/* delay changing these CSS props until the preview box transition is ended */\n\"\"}\n      transition: min-width 0s, border-radius 0s;\n      transition-delay: calc(var(--media-preview-transition-delay-out, 0s) + var(--media-preview-transition-duration-out, .25s));\n      background: var(--media-preview-time-background, var(--_preview-background));\n      border-radius: var(--media-preview-time-border-radius,\n        var(--media-preview-border-radius) var(--media-preview-border-radius)\n        var(--media-preview-border-radius) var(--media-preview-border-radius));\n      padding: var(--media-preview-time-padding, 3.5px 9px);\n      margin: var(--media-preview-time-margin, 0);\n      text-shadow: var(--media-preview-time-text-shadow, 0 0 4px rgb(0 0 0 / .75));\n      transform: translateX(min(\n        max(calc(50% - var(--_box-width) / 2),\n        calc(var(--_box-shift, 0))),\n        calc(var(--_box-width) / 2 - 50%)\n      ));\n    }\n\n    :host([${MediaUIAttributes.MEDIA_PREVIEW_IMAGE}]) media-preview-time-display,\n    :host([${MediaUIAttributes.MEDIA_PREVIEW_IMAGE}]) ::slotted(media-preview-time-display) {\n      transition-delay: var(--media-preview-transition-delay-in, .25s);\n      border-radius: var(--media-preview-time-border-radius,\n        0 0 var(--media-preview-border-radius) var(--media-preview-border-radius));\n      min-width: 100%;\n    }\n\n    :host([${MediaUIAttributes.MEDIA_PREVIEW_TIME}]:hover) {\n      --media-time-range-hover-display: block;\n    }\n\n    [part~=\"arrow\"],\n    ::slotted([part~=\"arrow\"]) {\n      display: var(--media-box-arrow-display, inline-block);\n      transform: translateX(min(\n        max(calc(50% - var(--_box-width) / 2 + var(--media-box-arrow-offset)),\n        calc(var(--_box-shift, 0))),\n        calc(var(--_box-width) / 2 - 50% - var(--media-box-arrow-offset))\n      ));\n      ${/* border-color has to come before border-top-color! */\n\"\"}\n      border-color: transparent;\n      border-top-color: var(--media-box-arrow-background, var(--_control-background));\n      border-width: var(--media-box-arrow-border-width,\n        var(--media-box-arrow-height, 5px) var(--media-box-arrow-width, 6px) 0);\n      border-style: solid;\n      justify-content: center;\n      height: 0;\n    }\n  </style>\n  <div id=\"preview-rail\">\n    <slot name=\"preview\" part=\"box preview-box\">\n      <media-preview-thumbnail></media-preview-thumbnail>\n      <media-preview-chapter-display></media-preview-chapter-display>\n      <media-preview-time-display></media-preview-time-display>\n      <slot name=\"preview-arrow\"><div part=\"arrow\"></div></slot>\n    </slot>\n  </div>\n  <div id=\"current-rail\">\n    <slot name=\"current\" part=\"box current-box\">\n      ${/* Example: add the current time w/ arrow to the playhead\n<media-time-display slot=\"current\"></media-time-display>\n<div part=\"arrow\" slot=\"current\"></div> */\n\"\"}\n    </slot>\n  </div>\n`;\nconst calcRangeValueFromTime = (el, time = el.mediaCurrentTime) => {\n  const startTime = Number.isFinite(el.mediaSeekableStart) ? el.mediaSeekableStart : 0;\n  const endTime = Number.isFinite(el.mediaDuration) ? el.mediaDuration : el.mediaSeekableEnd;\n  if (Number.isNaN(endTime))\n    return 0;\n  const value = (time - startTime) / (endTime - startTime);\n  return Math.max(0, Math.min(value, 1));\n};\nconst calcTimeFromRangeValue = (el, value = el.range.valueAsNumber) => {\n  const startTime = Number.isFinite(el.mediaSeekableStart) ? el.mediaSeekableStart : 0;\n  const endTime = Number.isFinite(el.mediaDuration) ? el.mediaDuration : el.mediaSeekableEnd;\n  if (Number.isNaN(endTime))\n    return 0;\n  return value * (endTime - startTime) + startTime;\n};\nclass MediaTimeRange extends MediaChromeRange {\n  constructor() {\n    super();\n    __privateAdd(this, _toggleRangeAnimation);\n    __privateAdd(this, _shouldRangeAnimate);\n    __privateAdd(this, _getElementRects);\n    /**\n     * Get the position, max and min for the box in percentage.\n     * It's important this is in percentage so when the player is resized\n     * the box will move accordingly.\n     */\n    __privateAdd(this, _getBoxPosition);\n    __privateAdd(this, _getBoxShiftPosition);\n    __privateAdd(this, _handlePointerMove);\n    __privateAdd(this, _previewRequest);\n    __privateAdd(this, _seekRequest);\n    __privateAdd(this, _rootNode, void 0);\n    __privateAdd(this, _animation, void 0);\n    __privateAdd(this, _boxes, void 0);\n    __privateAdd(this, _previewTime, void 0);\n    __privateAdd(this, _previewBox, void 0);\n    __privateAdd(this, _currentBox, void 0);\n    __privateAdd(this, _boxPaddingLeft, void 0);\n    __privateAdd(this, _boxPaddingRight, void 0);\n    __privateAdd(this, _mediaChaptersCues, void 0);\n    __privateAdd(this, _updateRange, (value) => {\n      if (this.dragging)\n        return;\n      if (isValidNumber(value)) {\n        this.range.valueAsNumber = value;\n      }\n      this.updateBar();\n    });\n    this.container.appendChild(template.content.cloneNode(true));\n    const track = this.shadowRoot.querySelector(\"#track\");\n    track.insertAdjacentHTML(\"afterbegin\", '<div id=\"buffered\" part=\"buffered\"></div>');\n    __privateSet(this, _boxes, this.shadowRoot.querySelectorAll('[part~=\"box\"]'));\n    __privateSet(this, _previewBox, this.shadowRoot.querySelector('[part~=\"preview-box\"]'));\n    __privateSet(this, _currentBox, this.shadowRoot.querySelector('[part~=\"current-box\"]'));\n    const computedStyle = getComputedStyle(this);\n    __privateSet(this, _boxPaddingLeft, parseInt(\n      computedStyle.getPropertyValue(\"--media-box-padding-left\")\n    ));\n    __privateSet(this, _boxPaddingRight, parseInt(\n      computedStyle.getPropertyValue(\"--media-box-padding-right\")\n    ));\n    __privateSet(this, _animation, new RangeAnimation(this.range, __privateGet(this, _updateRange), 60));\n  }\n  static get observedAttributes() {\n    return [\n      ...super.observedAttributes,\n      MediaUIAttributes.MEDIA_PAUSED,\n      MediaUIAttributes.MEDIA_DURATION,\n      MediaUIAttributes.MEDIA_SEEKABLE,\n      MediaUIAttributes.MEDIA_CURRENT_TIME,\n      MediaUIAttributes.MEDIA_PREVIEW_IMAGE,\n      MediaUIAttributes.MEDIA_PREVIEW_TIME,\n      MediaUIAttributes.MEDIA_PREVIEW_CHAPTER,\n      MediaUIAttributes.MEDIA_BUFFERED,\n      MediaUIAttributes.MEDIA_PLAYBACK_RATE,\n      MediaUIAttributes.MEDIA_LOADING,\n      MediaUIAttributes.MEDIA_ENDED\n    ];\n  }\n  connectedCallback() {\n    var _a;\n    super.connectedCallback();\n    this.range.setAttribute(\"aria-label\", nouns.SEEK());\n    __privateMethod(this, _toggleRangeAnimation, toggleRangeAnimation_fn).call(this);\n    __privateSet(this, _rootNode, this.getRootNode());\n    (_a = __privateGet(this, _rootNode)) == null ? void 0 : _a.addEventListener(\"transitionstart\", this);\n  }\n  disconnectedCallback() {\n    var _a;\n    super.disconnectedCallback();\n    __privateMethod(this, _toggleRangeAnimation, toggleRangeAnimation_fn).call(this);\n    (_a = __privateGet(this, _rootNode)) == null ? void 0 : _a.removeEventListener(\"transitionstart\", this);\n    __privateSet(this, _rootNode, null);\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    super.attributeChangedCallback(attrName, oldValue, newValue);\n    if (oldValue == newValue)\n      return;\n    if (attrName === MediaUIAttributes.MEDIA_CURRENT_TIME || attrName === MediaUIAttributes.MEDIA_PAUSED || attrName === MediaUIAttributes.MEDIA_ENDED || attrName === MediaUIAttributes.MEDIA_LOADING || attrName === MediaUIAttributes.MEDIA_DURATION || attrName === MediaUIAttributes.MEDIA_SEEKABLE) {\n      __privateGet(this, _animation).update({\n        start: calcRangeValueFromTime(this),\n        duration: this.mediaSeekableEnd - this.mediaSeekableStart,\n        playbackRate: this.mediaPlaybackRate\n      });\n      __privateMethod(this, _toggleRangeAnimation, toggleRangeAnimation_fn).call(this);\n      updateAriaValueText(this);\n    } else if (attrName === MediaUIAttributes.MEDIA_BUFFERED) {\n      this.updateBufferedBar();\n    }\n    if (attrName === MediaUIAttributes.MEDIA_DURATION || attrName === MediaUIAttributes.MEDIA_SEEKABLE) {\n      this.mediaChaptersCues = __privateGet(this, _mediaChaptersCues);\n      this.updateBar();\n    }\n  }\n  get mediaChaptersCues() {\n    return __privateGet(this, _mediaChaptersCues);\n  }\n  set mediaChaptersCues(value) {\n    var _a;\n    __privateSet(this, _mediaChaptersCues, value);\n    this.updateSegments(\n      (_a = __privateGet(this, _mediaChaptersCues)) == null ? void 0 : _a.map((c) => ({\n        start: calcRangeValueFromTime(this, c.startTime),\n        end: calcRangeValueFromTime(this, c.endTime)\n      }))\n    );\n  }\n  /**\n   * Is the media paused\n   */\n  get mediaPaused() {\n    return getBooleanAttr(this, MediaUIAttributes.MEDIA_PAUSED);\n  }\n  set mediaPaused(value) {\n    setBooleanAttr(this, MediaUIAttributes.MEDIA_PAUSED, value);\n  }\n  /**\n   * Is the media loading\n   */\n  get mediaLoading() {\n    return getBooleanAttr(this, MediaUIAttributes.MEDIA_LOADING);\n  }\n  set mediaLoading(value) {\n    setBooleanAttr(this, MediaUIAttributes.MEDIA_LOADING, value);\n  }\n  /**\n   *\n   */\n  get mediaDuration() {\n    return getNumericAttr(this, MediaUIAttributes.MEDIA_DURATION);\n  }\n  set mediaDuration(value) {\n    setNumericAttr(this, MediaUIAttributes.MEDIA_DURATION, value);\n  }\n  /**\n   *\n   */\n  get mediaCurrentTime() {\n    return getNumericAttr(this, MediaUIAttributes.MEDIA_CURRENT_TIME);\n  }\n  set mediaCurrentTime(value) {\n    setNumericAttr(this, MediaUIAttributes.MEDIA_CURRENT_TIME, value);\n  }\n  /**\n   *\n   */\n  get mediaPlaybackRate() {\n    return getNumericAttr(this, MediaUIAttributes.MEDIA_PLAYBACK_RATE, 1);\n  }\n  set mediaPlaybackRate(value) {\n    setNumericAttr(this, MediaUIAttributes.MEDIA_PLAYBACK_RATE, value);\n  }\n  /**\n   * An array of ranges, each range being an array of two numbers.\n   * e.g. [[1, 2], [3, 4]]\n   */\n  get mediaBuffered() {\n    const buffered = this.getAttribute(MediaUIAttributes.MEDIA_BUFFERED);\n    if (!buffered)\n      return [];\n    return buffered.split(\" \").map((timePair) => timePair.split(\":\").map((timeStr) => +timeStr));\n  }\n  set mediaBuffered(list) {\n    if (!list) {\n      this.removeAttribute(MediaUIAttributes.MEDIA_BUFFERED);\n      return;\n    }\n    const strVal = list.map((tuple) => tuple.join(\":\")).join(\" \");\n    this.setAttribute(MediaUIAttributes.MEDIA_BUFFERED, strVal);\n  }\n  /**\n   * Range of values that can be seeked to\n   * An array of two numbers [start, end]\n   */\n  get mediaSeekable() {\n    const seekable = this.getAttribute(MediaUIAttributes.MEDIA_SEEKABLE);\n    if (!seekable)\n      return void 0;\n    return seekable.split(\":\").map((time) => +time);\n  }\n  set mediaSeekable(range) {\n    if (range == null) {\n      this.removeAttribute(MediaUIAttributes.MEDIA_SEEKABLE);\n      return;\n    }\n    this.setAttribute(MediaUIAttributes.MEDIA_SEEKABLE, range.join(\":\"));\n  }\n  /**\n   *\n   */\n  get mediaSeekableEnd() {\n    var _a;\n    const [, end = this.mediaDuration] = (_a = this.mediaSeekable) != null ? _a : [];\n    return end;\n  }\n  get mediaSeekableStart() {\n    var _a;\n    const [start = 0] = (_a = this.mediaSeekable) != null ? _a : [];\n    return start;\n  }\n  /**\n   * The url of the preview image\n   */\n  get mediaPreviewImage() {\n    return getStringAttr(this, MediaUIAttributes.MEDIA_PREVIEW_IMAGE);\n  }\n  set mediaPreviewImage(value) {\n    setStringAttr(this, MediaUIAttributes.MEDIA_PREVIEW_IMAGE, value);\n  }\n  /**\n   *\n   */\n  get mediaPreviewTime() {\n    return getNumericAttr(this, MediaUIAttributes.MEDIA_PREVIEW_TIME);\n  }\n  set mediaPreviewTime(value) {\n    setNumericAttr(this, MediaUIAttributes.MEDIA_PREVIEW_TIME, value);\n  }\n  /**\n   *\n   */\n  get mediaEnded() {\n    return getBooleanAttr(this, MediaUIAttributes.MEDIA_ENDED);\n  }\n  set mediaEnded(value) {\n    setBooleanAttr(this, MediaUIAttributes.MEDIA_ENDED, value);\n  }\n  /* Add a buffered progress bar */\n  updateBar() {\n    super.updateBar();\n    this.updateBufferedBar();\n    this.updateCurrentBox();\n  }\n  updateBufferedBar() {\n    var _a;\n    const buffered = this.mediaBuffered;\n    if (!buffered.length) {\n      return;\n    }\n    let relativeBufferedEnd;\n    if (!this.mediaEnded) {\n      const currentTime = this.mediaCurrentTime;\n      const [, bufferedEnd = this.mediaSeekableStart] = (_a = buffered.find(\n        ([start, end]) => start <= currentTime && currentTime <= end\n      )) != null ? _a : [];\n      relativeBufferedEnd = calcRangeValueFromTime(this, bufferedEnd);\n    } else {\n      relativeBufferedEnd = 1;\n    }\n    const { style } = getOrInsertCSSRule(this.shadowRoot, \"#buffered\");\n    style.setProperty(\"width\", `${relativeBufferedEnd * 100}%`);\n  }\n  updateCurrentBox() {\n    const currentSlot = this.shadowRoot.querySelector(\n      'slot[name=\"current\"]'\n    );\n    if (!currentSlot.assignedElements().length)\n      return;\n    const currentRailRule = getOrInsertCSSRule(\n      this.shadowRoot,\n      \"#current-rail\"\n    );\n    const currentBoxRule = getOrInsertCSSRule(\n      this.shadowRoot,\n      '[part~=\"current-box\"]'\n    );\n    const rects = __privateMethod(this, _getElementRects, getElementRects_fn).call(this, __privateGet(this, _currentBox));\n    const boxPos = __privateMethod(this, _getBoxPosition, getBoxPosition_fn).call(this, rects, this.range.valueAsNumber);\n    const boxShift = __privateMethod(this, _getBoxShiftPosition, getBoxShiftPosition_fn).call(this, rects, this.range.valueAsNumber);\n    currentRailRule.style.transform = `translateX(${boxPos})`;\n    currentRailRule.style.setProperty(\"--_range-width\", `${rects.range.width}`);\n    currentBoxRule.style.setProperty(\"--_box-shift\", `${boxShift}`);\n    currentBoxRule.style.setProperty(\"--_box-width\", `${rects.box.width}px`);\n    currentBoxRule.style.setProperty(\"visibility\", \"initial\");\n  }\n  handleEvent(evt) {\n    super.handleEvent(evt);\n    switch (evt.type) {\n      case \"input\":\n        __privateMethod(this, _seekRequest, seekRequest_fn).call(this);\n        break;\n      case \"pointermove\":\n        __privateMethod(this, _handlePointerMove, handlePointerMove_fn).call(this, evt);\n        break;\n      case \"pointerup\":\n      case \"pointerleave\":\n        __privateMethod(this, _previewRequest, previewRequest_fn).call(this, null);\n        break;\n      case \"transitionstart\":\n        if (containsComposedNode(evt.target, this)) {\n          setTimeout(() => __privateMethod(this, _toggleRangeAnimation, toggleRangeAnimation_fn).call(this), 0);\n        }\n        break;\n    }\n  }\n}\n_rootNode = new WeakMap();\n_animation = new WeakMap();\n_boxes = new WeakMap();\n_previewTime = new WeakMap();\n_previewBox = new WeakMap();\n_currentBox = new WeakMap();\n_boxPaddingLeft = new WeakMap();\n_boxPaddingRight = new WeakMap();\n_mediaChaptersCues = new WeakMap();\n_toggleRangeAnimation = new WeakSet();\ntoggleRangeAnimation_fn = function() {\n  if (__privateMethod(this, _shouldRangeAnimate, shouldRangeAnimate_fn).call(this)) {\n    __privateGet(this, _animation).start();\n  } else {\n    __privateGet(this, _animation).stop();\n  }\n};\n_shouldRangeAnimate = new WeakSet();\nshouldRangeAnimate_fn = function() {\n  return this.isConnected && !this.mediaPaused && !this.mediaLoading && !this.mediaEnded && this.mediaSeekableEnd > 0 && isElementVisible(this);\n};\n_updateRange = new WeakMap();\n_getElementRects = new WeakSet();\ngetElementRects_fn = function(box) {\n  var _a;\n  const bounds = (_a = this.getAttribute(\"bounds\") ? closestComposedNode(this, `#${this.getAttribute(\"bounds\")}`) : this.parentElement) != null ? _a : this;\n  const boundsRect = bounds.getBoundingClientRect();\n  const rangeRect = this.range.getBoundingClientRect();\n  const width = box.offsetWidth;\n  const min = -(rangeRect.left - boundsRect.left - width / 2);\n  const max = boundsRect.right - rangeRect.left - width / 2;\n  return {\n    box: { width, min, max },\n    bounds: boundsRect,\n    range: rangeRect\n  };\n};\n_getBoxPosition = new WeakSet();\ngetBoxPosition_fn = function(rects, ratio) {\n  let position = `${ratio * 100}%`;\n  const { width, min, max } = rects.box;\n  if (!width)\n    return position;\n  if (!Number.isNaN(min)) {\n    const pad = `var(--media-box-padding-left)`;\n    const minPos = `calc(1 / var(--_range-width) * 100 * ${min}% + ${pad})`;\n    position = `max(${minPos}, ${position})`;\n  }\n  if (!Number.isNaN(max)) {\n    const pad = `var(--media-box-padding-right)`;\n    const maxPos = `calc(1 / var(--_range-width) * 100 * ${max}% - ${pad})`;\n    position = `min(${position}, ${maxPos})`;\n  }\n  return position;\n};\n_getBoxShiftPosition = new WeakSet();\ngetBoxShiftPosition_fn = function(rects, ratio) {\n  const { width, min, max } = rects.box;\n  const pointerX = ratio * rects.range.width;\n  if (pointerX < min + __privateGet(this, _boxPaddingLeft)) {\n    const offset = rects.range.left - rects.bounds.left - __privateGet(this, _boxPaddingLeft);\n    return `${pointerX - width / 2 + offset}px`;\n  }\n  if (pointerX > max - __privateGet(this, _boxPaddingRight)) {\n    const offset = rects.bounds.right - rects.range.right - __privateGet(this, _boxPaddingRight);\n    return `${pointerX + width / 2 - offset - rects.range.width}px`;\n  }\n  return 0;\n};\n_handlePointerMove = new WeakSet();\nhandlePointerMove_fn = function(evt) {\n  const isOverBoxes = [...__privateGet(this, _boxes)].some(\n    (b) => evt.composedPath().includes(b)\n  );\n  if (!this.dragging && (isOverBoxes || !evt.composedPath().includes(this))) {\n    __privateMethod(this, _previewRequest, previewRequest_fn).call(this, null);\n    return;\n  }\n  const duration = this.mediaSeekableEnd;\n  if (!duration)\n    return;\n  const previewRailRule = getOrInsertCSSRule(\n    this.shadowRoot,\n    \"#preview-rail\"\n  );\n  const previewBoxRule = getOrInsertCSSRule(\n    this.shadowRoot,\n    '[part~=\"preview-box\"]'\n  );\n  const rects = __privateMethod(this, _getElementRects, getElementRects_fn).call(this, __privateGet(this, _previewBox));\n  let pointerRatio = (evt.clientX - rects.range.left) / rects.range.width;\n  pointerRatio = Math.max(0, Math.min(1, pointerRatio));\n  const boxPos = __privateMethod(this, _getBoxPosition, getBoxPosition_fn).call(this, rects, pointerRatio);\n  const boxShift = __privateMethod(this, _getBoxShiftPosition, getBoxShiftPosition_fn).call(this, rects, pointerRatio);\n  previewRailRule.style.transform = `translateX(${boxPos})`;\n  previewRailRule.style.setProperty(\"--_range-width\", `${rects.range.width}`);\n  previewBoxRule.style.setProperty(\"--_box-shift\", `${boxShift}`);\n  previewBoxRule.style.setProperty(\"--_box-width\", `${rects.box.width}px`);\n  const diff = Math.round(__privateGet(this, _previewTime)) - Math.round(pointerRatio * duration);\n  if (Math.abs(diff) < 1 && pointerRatio > 0.01 && pointerRatio < 0.99)\n    return;\n  __privateSet(this, _previewTime, pointerRatio * duration);\n  __privateMethod(this, _previewRequest, previewRequest_fn).call(this, __privateGet(this, _previewTime));\n};\n_previewRequest = new WeakSet();\npreviewRequest_fn = function(detail) {\n  this.dispatchEvent(\n    new globalThis.CustomEvent(MediaUIEvents.MEDIA_PREVIEW_REQUEST, {\n      composed: true,\n      bubbles: true,\n      detail\n    })\n  );\n};\n_seekRequest = new WeakSet();\nseekRequest_fn = function() {\n  __privateGet(this, _animation).stop();\n  const detail = calcTimeFromRangeValue(this);\n  this.dispatchEvent(\n    new globalThis.CustomEvent(MediaUIEvents.MEDIA_SEEK_REQUEST, {\n      composed: true,\n      bubbles: true,\n      detail\n    })\n  );\n};\nif (!globalThis.customElements.get(\"media-time-range\")) {\n  globalThis.customElements.define(\"media-time-range\", MediaTimeRange);\n}\nvar media_time_range_default = MediaTimeRange;\nexport {\n  media_time_range_default as default\n};\n", "import {\n  closestComposedNode,\n  getMediaController,\n  getStringAttr,\n  setStringAttr\n} from \"./utils/element-utils.js\";\nimport { globalThis, document } from \"./utils/server-safe-globals.js\";\nconst Attributes = {\n  PLACEMENT: \"placement\",\n  BOUNDS: \"bounds\"\n};\nconst template = document.createElement(\"template\");\ntemplate.innerHTML = /*html*/\n`\n  <style>\n    :host {\n      --_tooltip-background-color: var(--media-tooltip-background-color, var(--media-secondary-color, rgba(20, 20, 30, .7)));\n      --_tooltip-background: var(--media-tooltip-background, var(--_tooltip-background-color));\n      --_tooltip-arrow-half-width: calc(var(--media-tooltip-arrow-width, 12px) / 2);\n      --_tooltip-arrow-height: var(--media-tooltip-arrow-height, 5px);\n      --_tooltip-arrow-background: var(--media-tooltip-arrow-color, var(--_tooltip-background-color));\n      position: relative;\n      pointer-events: none;\n      display: var(--media-tooltip-display, inline-flex);\n      justify-content: center;\n      align-items: center;\n      box-sizing: border-box;\n      z-index: var(--media-tooltip-z-index, 1);\n      background: var(--_tooltip-background);\n      color: var(--media-text-color, var(--media-primary-color, rgb(238 238 238)));\n      font: var(--media-font,\n        var(--media-font-weight, 400)\n        var(--media-font-size, 13px) /\n        var(--media-text-content-height, var(--media-control-height, 18px))\n        var(--media-font-family, helvetica neue, segoe ui, roboto, arial, sans-serif));\n      padding: var(--media-tooltip-padding, .35em .7em);\n      border: var(--media-tooltip-border, none);\n      border-radius: var(--media-tooltip-border-radius, 5px);\n      filter: var(--media-tooltip-filter, drop-shadow(0 0 4px rgba(0, 0, 0, .2)));\n      white-space: var(--media-tooltip-white-space, nowrap);\n    }\n\n    :host([hidden]) {\n      display: none;\n    }\n\n    img, svg {\n      display: inline-block;\n    }\n\n    #arrow {\n      position: absolute;\n      width: 0px;\n      height: 0px;\n      border-style: solid;\n      display: var(--media-tooltip-arrow-display, block);\n    }\n\n    :host(:not([placement])),\n    :host([placement=\"top\"]) {\n      position: absolute;\n      bottom: calc(100% + var(--media-tooltip-distance, 12px));\n      left: 50%;\n      transform: translate(calc(-50% - var(--media-tooltip-offset-x, 0px)), 0);\n    }\n    :host(:not([placement])) #arrow,\n    :host([placement=\"top\"]) #arrow {\n      top: 100%;\n      left: 50%;\n      border-width: var(--_tooltip-arrow-height) var(--_tooltip-arrow-half-width) 0 var(--_tooltip-arrow-half-width);\n      border-color: var(--_tooltip-arrow-background) transparent transparent transparent;\n      transform: translate(calc(-50% + var(--media-tooltip-offset-x, 0px)), 0);\n    }\n\n    :host([placement=\"right\"]) {\n      position: absolute;\n      left: calc(100% + var(--media-tooltip-distance, 12px));\n      top: 50%;\n      transform: translate(0, -50%);\n    }\n    :host([placement=\"right\"]) #arrow {\n      top: 50%;\n      right: 100%;\n      border-width: var(--_tooltip-arrow-half-width) var(--_tooltip-arrow-height) var(--_tooltip-arrow-half-width) 0;\n      border-color: transparent var(--_tooltip-arrow-background) transparent transparent;\n      transform: translate(0, -50%);\n    }\n\n    :host([placement=\"bottom\"]) {\n      position: absolute;\n      top: calc(100% + var(--media-tooltip-distance, 12px));\n      left: 50%;\n      transform: translate(calc(-50% - var(--media-tooltip-offset-x, 0px)), 0);\n    }\n    :host([placement=\"bottom\"]) #arrow {\n      bottom: 100%;\n      left: 50%;\n      border-width: 0 var(--_tooltip-arrow-half-width) var(--_tooltip-arrow-height) var(--_tooltip-arrow-half-width);\n      border-color: transparent transparent var(--_tooltip-arrow-background) transparent;\n      transform: translate(calc(-50% + var(--media-tooltip-offset-x, 0px)), 0);\n    }\n\n    :host([placement=\"left\"]) {\n      position: absolute;\n      right: calc(100% + var(--media-tooltip-distance, 12px));\n      top: 50%;\n      transform: translate(0, -50%);\n    }\n    :host([placement=\"left\"]) #arrow {\n      top: 50%;\n      left: 100%;\n      border-width: var(--_tooltip-arrow-half-width) 0 var(--_tooltip-arrow-half-width) var(--_tooltip-arrow-height);\n      border-color: transparent transparent transparent var(--_tooltip-arrow-background);\n      transform: translate(0, -50%);\n    }\n    \n    :host([placement=\"none\"]) #arrow {\n      display: none;\n    }\n\n  </style>\n  <slot></slot>\n  <div id=\"arrow\"></div>\n`;\nclass MediaTooltip extends globalThis.HTMLElement {\n  constructor() {\n    super();\n    // Adjusts tooltip position relative to the closest specified container\n    // such that it doesn't spill out of the left or right sides. Only applies\n    // to 'top' and 'bottom' placed tooltips.\n    this.updateXOffset = () => {\n      var _a;\n      const placement = this.placement;\n      if (placement === \"left\" || placement === \"right\") {\n        this.style.removeProperty(\"--media-tooltip-offset-x\");\n        return;\n      }\n      const tooltipStyle = getComputedStyle(this);\n      const containingEl = (_a = closestComposedNode(this, \"#\" + this.bounds)) != null ? _a : getMediaController(this);\n      if (!containingEl)\n        return;\n      const { x: containerX, width: containerWidth } = containingEl.getBoundingClientRect();\n      const { x: tooltipX, width: tooltipWidth } = this.getBoundingClientRect();\n      const tooltipRight = tooltipX + tooltipWidth;\n      const containerRight = containerX + containerWidth;\n      const offsetXVal = tooltipStyle.getPropertyValue(\n        \"--media-tooltip-offset-x\"\n      );\n      const currOffsetX = offsetXVal ? parseFloat(offsetXVal.replace(\"px\", \"\")) : 0;\n      const marginVal = tooltipStyle.getPropertyValue(\n        \"--media-tooltip-container-margin\"\n      );\n      const currMargin = marginVal ? parseFloat(marginVal.replace(\"px\", \"\")) : 0;\n      const leftDiff = tooltipX - containerX + currOffsetX - currMargin;\n      const rightDiff = tooltipRight - containerRight + currOffsetX + currMargin;\n      if (leftDiff < 0) {\n        this.style.setProperty(\"--media-tooltip-offset-x\", `${leftDiff}px`);\n        return;\n      }\n      if (rightDiff > 0) {\n        this.style.setProperty(\"--media-tooltip-offset-x\", `${rightDiff}px`);\n        return;\n      }\n      this.style.removeProperty(\"--media-tooltip-offset-x\");\n    };\n    if (!this.shadowRoot) {\n      this.attachShadow({ mode: \"open\" });\n      this.shadowRoot.appendChild(template.content.cloneNode(true));\n    }\n    this.arrowEl = this.shadowRoot.querySelector(\"#arrow\");\n    if (Object.prototype.hasOwnProperty.call(this, \"placement\")) {\n      const placement = this.placement;\n      delete this.placement;\n      this.placement = placement;\n    }\n  }\n  static get observedAttributes() {\n    return [Attributes.PLACEMENT, Attributes.BOUNDS];\n  }\n  /**\n   * Get or set tooltip placement\n   */\n  get placement() {\n    return getStringAttr(this, Attributes.PLACEMENT);\n  }\n  set placement(value) {\n    setStringAttr(this, Attributes.PLACEMENT, value);\n  }\n  /**\n   * Get or set tooltip container ID selector that will constrain the tooltips\n   * horizontal position.\n   */\n  get bounds() {\n    return getStringAttr(this, Attributes.BOUNDS);\n  }\n  set bounds(value) {\n    setStringAttr(this, Attributes.BOUNDS, value);\n  }\n}\nif (!globalThis.customElements.get(\"media-tooltip\")) {\n  globalThis.customElements.define(\"media-tooltip\", MediaTooltip);\n}\nvar media_tooltip_default = MediaTooltip;\nexport {\n  Attributes,\n  media_tooltip_default as default\n};\n", "import { globalThis } from \"./utils/server-safe-globals.js\";\nimport { MediaChromeRange } from \"./media-chrome-range.js\";\nimport { MediaUIAttributes, MediaUIEvents } from \"./constants.js\";\nimport { nouns } from \"./labels/labels.js\";\nimport {\n  getBooleanAttr,\n  getNumericAttr,\n  getStringAttr,\n  setBooleanAttr,\n  setNumericAttr,\n  setStringAttr\n} from \"./utils/element-utils.js\";\nconst DEFAULT_VOLUME = 1;\nconst toVolume = (el) => {\n  if (el.mediaMuted)\n    return 0;\n  return el.mediaVolume;\n};\nconst formatAsPercentString = (value) => `${Math.round(value * 100)}%`;\nclass MediaVolumeRange extends MediaChromeRange {\n  static get observedAttributes() {\n    return [\n      ...super.observedAttributes,\n      MediaUIAttributes.MEDIA_VOLUME,\n      MediaUIAttributes.MEDIA_MUTED,\n      MediaUIAttributes.MEDIA_VOLUME_UNAVAILABLE\n    ];\n  }\n  constructor() {\n    super();\n    this.range.addEventListener(\"input\", () => {\n      const detail = this.range.value;\n      const evt = new globalThis.CustomEvent(\n        MediaUIEvents.MEDIA_VOLUME_REQUEST,\n        {\n          composed: true,\n          bubbles: true,\n          detail\n        }\n      );\n      this.dispatchEvent(evt);\n    });\n  }\n  connectedCallback() {\n    super.connectedCallback();\n    this.range.setAttribute(\"aria-label\", nouns.VOLUME());\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    super.attributeChangedCallback(attrName, oldValue, newValue);\n    if (attrName === MediaUIAttributes.MEDIA_VOLUME || attrName === MediaUIAttributes.MEDIA_MUTED) {\n      this.range.valueAsNumber = toVolume(this);\n      this.range.setAttribute(\n        \"aria-valuetext\",\n        formatAsPercentString(this.range.valueAsNumber)\n      );\n      this.updateBar();\n    }\n  }\n  /**\n   *\n   */\n  get mediaVolume() {\n    return getNumericAttr(this, MediaUIAttributes.MEDIA_VOLUME, DEFAULT_VOLUME);\n  }\n  set mediaVolume(value) {\n    setNumericAttr(this, MediaUIAttributes.MEDIA_VOLUME, value);\n  }\n  /**\n   * Is the media currently muted\n   */\n  get mediaMuted() {\n    return getBooleanAttr(this, MediaUIAttributes.MEDIA_MUTED);\n  }\n  set mediaMuted(value) {\n    setBooleanAttr(this, MediaUIAttributes.MEDIA_MUTED, value);\n  }\n  /**\n   * The volume unavailability state\n   */\n  get mediaVolumeUnavailable() {\n    return getStringAttr(this, MediaUIAttributes.MEDIA_VOLUME_UNAVAILABLE);\n  }\n  set mediaVolumeUnavailable(value) {\n    setStringAttr(this, MediaUIAttributes.MEDIA_VOLUME_UNAVAILABLE, value);\n  }\n}\nif (!globalThis.customElements.get(\"media-volume-range\")) {\n  globalThis.customElements.define(\"media-volume-range\", MediaVolumeRange);\n}\nvar media_volume_range_default = MediaVolumeRange;\nexport {\n  media_volume_range_default as default\n};\n", "var zr=Object.create;var ct=Object.defineProperty;var Kr=Object.getOwnPropertyDescriptor;var Yr=Object.getOwnPropertyNames;var Xr=Object.getPrototypeOf,$r=Object.prototype.hasOwnProperty;var _t=function(r,e){return function(){return r&&(e=r(r=0)),e}};var B=function(r,e){return function(){return e||r((e={exports:{}}).exports,e),e.exports}};var Zr=function(r,e,t,i){if(e&&typeof e==\"object\"||typeof e==\"function\")for(var a=Yr(e),n=0,o=a.length,s;n<o;n++)s=a[n],!$r.call(r,s)&&s!==t&&ct(r,s,{get:function(u){return e[u]}.bind(null,s),enumerable:!(i=Kr(e,s))||i.enumerable});return r};var J=function(r,e,t){return t=r!=null?zr(Xr(r)):{},Zr(e||!r||!r.__esModule?ct(t,\"default\",{value:r,enumerable:!0}):t,r)};var Q=B(function(Vi,mt){var xe;typeof window!=\"undefined\"?xe=window:typeof global!=\"undefined\"?xe=global:typeof self!=\"undefined\"?xe=self:xe={};mt.exports=xe});function U(r,e){return e!=null&&typeof Symbol!=\"undefined\"&&e[Symbol.hasInstance]?!!e[Symbol.hasInstance](r):U(r,e)}var te=_t(function(){te()});function Ne(r){\"@swc/helpers - typeof\";return r&&typeof Symbol!=\"undefined\"&&r.constructor===Symbol?\"symbol\":typeof r}var Ge=_t(function(){});var Ke=B(function(Eu,vr){var pr=Array.prototype.slice;vr.exports=Ja;function Ja(r,e){for((\"length\"in r)||(r=[r]),r=pr.call(r);r.length;){var t=r.shift(),i=e(t);if(i)return i;t.childNodes&&t.childNodes.length&&(r=pr.call(t.childNodes).concat(r))}}});var hr=B(function(xu,mr){te();mr.exports=me;function me(r,e){if(!U(this,me))return new me(r,e);this.data=r,this.nodeValue=r,this.length=r.length,this.ownerDocument=e||null}me.prototype.nodeType=8;me.prototype.nodeName=\"#comment\";me.prototype.toString=function(){return\"[object Comment]\"}});var gr=B(function(Su,yr){te();yr.exports=ie;function ie(r,e){if(!U(this,ie))return new ie(r);this.data=r||\"\",this.length=this.data.length,this.ownerDocument=e||null}ie.prototype.type=\"DOMTextNode\";ie.prototype.nodeType=3;ie.prototype.nodeName=\"#text\";ie.prototype.toString=function(){return this.data};ie.prototype.replaceData=function(e,t,i){var a=this.data,n=a.substring(0,e),o=a.substring(e+t,a.length);this.data=n+i+o,this.length=this.data.length}});var Ye=B(function(Ru,br){br.exports=Qa;function Qa(r){var e=this,t=r.type;r.target||(r.target=e),e.listeners||(e.listeners={});var i=e.listeners[t];if(i)return i.forEach(function(a){r.currentTarget=e,typeof a==\"function\"?a(r):a.handleEvent(r)});e.parentNode&&e.parentNode.dispatchEvent(r)}});var Xe=B(function(qu,Tr){Tr.exports=za;function za(r,e){var t=this;t.listeners||(t.listeners={}),t.listeners[r]||(t.listeners[r]=[]),t.listeners[r].indexOf(e)===-1&&t.listeners[r].push(e)}});var $e=B(function(Au,wr){wr.exports=Ka;function Ka(r,e){var t=this;if(t.listeners&&t.listeners[r]){var i=t.listeners[r],a=i.indexOf(e);a!==-1&&i.splice(a,1)}}});var Dr=B(function(Iu,xr){Ge();xr.exports=Er;var Ya=[\"area\",\"base\",\"br\",\"col\",\"embed\",\"hr\",\"img\",\"input\",\"keygen\",\"link\",\"menuitem\",\"meta\",\"param\",\"source\",\"track\",\"wbr\"];function Er(r){switch(r.nodeType){case 3:return Ze(r.data);case 8:return\"<!--\"+r.data+\"-->\";default:return Xa(r)}}function Xa(r){var e=[],t=r.tagName;return r.namespaceURI===\"http://www.w3.org/1999/xhtml\"&&(t=t.toLowerCase()),e.push(\"<\"+t+ti(r)+ei(r)),Ya.indexOf(t)>-1?e.push(\" />\"):(e.push(\">\"),r.childNodes.length?e.push.apply(e,r.childNodes.map(Er)):r.textContent||r.innerText?e.push(Ze(r.textContent||r.innerText)):r.innerHTML&&e.push(r.innerHTML),e.push(\"</\"+t+\">\")),e.join(\"\")}function $a(r,e){var t=Ne(r[e]);return e===\"style\"&&Object.keys(r.style).length>0?!0:r.hasOwnProperty(e)&&(t===\"string\"||t===\"boolean\"||t===\"number\")&&e!==\"nodeName\"&&e!==\"className\"&&e!==\"tagName\"&&e!==\"textContent\"&&e!==\"innerText\"&&e!==\"namespaceURI\"&&e!==\"innerHTML\"}function Za(r){if(typeof r==\"string\")return r;var e=\"\";return Object.keys(r).forEach(function(t){var i=r[t];t=t.replace(/[A-Z]/g,function(a){return\"-\"+a.toLowerCase()}),e+=t+\":\"+i+\";\"}),e}function ei(r){var e=r.dataset,t=[];for(var i in e)t.push({name:\"data-\"+i,value:e[i]});return t.length?kr(t):\"\"}function kr(r){var e=[];return r.forEach(function(t){var i=t.name,a=t.value;i===\"style\"&&(a=Za(a)),e.push(i+'=\"'+ri(a)+'\"')}),e.length?\" \"+e.join(\" \"):\"\"}function ti(r){var e=[];for(var t in r)$a(r,t)&&e.push({name:t,value:r[t]});for(var i in r._attributes)for(var a in r._attributes[i]){var n=r._attributes[i][a],o=(n.prefix?n.prefix+\":\":\"\")+a;e.push({name:o,value:n.value})}return r.className&&e.push({name:\"class\",value:r.className}),e.length?kr(e):\"\"}function Ze(r){var e=\"\";return typeof r==\"string\"?e=r:r&&(e=r.toString()),e.replace(/&/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\")}function ri(r){return Ze(r).replace(/\"/g,\"&quot;\")}});var tt=B(function(Nu,Rr){te();var et=Ke(),ai=Ye(),ii=Xe(),ni=$e(),oi=Dr(),Sr=\"http://www.w3.org/1999/xhtml\";Rr.exports=P;function P(r,e,t){if(!U(this,P))return new P(r);var i=t===void 0?Sr:t||null;this.tagName=i===Sr?String(r).toUpperCase():r,this.nodeName=this.tagName,this.className=\"\",this.dataset={},this.childNodes=[],this.parentNode=null,this.style={},this.ownerDocument=e||null,this.namespaceURI=i,this._attributes={},this.tagName===\"INPUT\"&&(this.type=\"text\")}P.prototype.type=\"DOMElement\";P.prototype.nodeType=1;P.prototype.appendChild=function(e){return e.parentNode&&e.parentNode.removeChild(e),this.childNodes.push(e),e.parentNode=this,e};P.prototype.replaceChild=function(e,t){e.parentNode&&e.parentNode.removeChild(e);var i=this.childNodes.indexOf(t);return t.parentNode=null,this.childNodes[i]=e,e.parentNode=this,t};P.prototype.removeChild=function(e){var t=this.childNodes.indexOf(e);return this.childNodes.splice(t,1),e.parentNode=null,e};P.prototype.insertBefore=function(e,t){e.parentNode&&e.parentNode.removeChild(e);var i=t==null?-1:this.childNodes.indexOf(t);return i>-1?this.childNodes.splice(i,0,e):this.childNodes.push(e),e.parentNode=this,e};P.prototype.setAttributeNS=function(e,t,i){var a=null,n=t,o=t.indexOf(\":\");if(o>-1&&(a=t.substr(0,o),n=t.substr(o+1)),this.tagName===\"INPUT\"&&t===\"type\")this.type=i;else{var s=this._attributes[e]||(this._attributes[e]={});s[n]={value:i,prefix:a}}};P.prototype.getAttributeNS=function(e,t){var i=this._attributes[e],a=i&&i[t]&&i[t].value;return this.tagName===\"INPUT\"&&t===\"type\"?this.type:typeof a!=\"string\"?null:a};P.prototype.removeAttributeNS=function(e,t){var i=this._attributes[e];i&&delete i[t]};P.prototype.hasAttributeNS=function(e,t){var i=this._attributes[e];return!!i&&t in i};P.prototype.setAttribute=function(e,t){return this.setAttributeNS(null,e,t)};P.prototype.getAttribute=function(e){return this.getAttributeNS(null,e)};P.prototype.removeAttribute=function(e){return this.removeAttributeNS(null,e)};P.prototype.hasAttribute=function(e){return this.hasAttributeNS(null,e)};P.prototype.removeEventListener=ni;P.prototype.addEventListener=ii;P.prototype.dispatchEvent=ai;P.prototype.focus=function(){};P.prototype.toString=function(){return oi(this)};P.prototype.getElementsByClassName=function(e){var t=e.split(\" \"),i=[];return et(this,function(a){if(a.nodeType===1){var n=a.className||\"\",o=n.split(\" \");t.every(function(s){return o.indexOf(s)!==-1})&&i.push(a)}}),i};P.prototype.getElementsByTagName=function(e){e=e.toLowerCase();var t=[];return et(this.childNodes,function(i){i.nodeType===1&&(e===\"*\"||i.tagName.toLowerCase()===e)&&t.push(i)}),t};P.prototype.contains=function(e){return et(this,function(t){return e===t})||!1}});var Ar=B(function(Cu,qr){te();var rt=tt();qr.exports=K;function K(r){if(!U(this,K))return new K;this.childNodes=[],this.parentNode=null,this.ownerDocument=r||null}K.prototype.type=\"DocumentFragment\";K.prototype.nodeType=11;K.prototype.nodeName=\"#document-fragment\";K.prototype.appendChild=rt.prototype.appendChild;K.prototype.replaceChild=rt.prototype.replaceChild;K.prototype.removeChild=rt.prototype.removeChild;K.prototype.toString=function(){return this.childNodes.map(function(e){return String(e)}).join(\"\")}});var Ir=B(function(Mu,Or){Or.exports=at;function at(r){}at.prototype.initEvent=function(e,t,i){this.type=e,this.bubbles=t,this.cancelable=i};at.prototype.preventDefault=function(){}});var Nr=B(function(Bu,Pr){te();var si=Ke(),ui=hr(),di=gr(),Re=tt(),li=Ar(),ci=Ir(),_i=Ye(),fi=Xe(),pi=$e();Pr.exports=Ue;function Ue(){if(!U(this,Ue))return new Ue;this.head=this.createElement(\"head\"),this.body=this.createElement(\"body\"),this.documentElement=this.createElement(\"html\"),this.documentElement.appendChild(this.head),this.documentElement.appendChild(this.body),this.childNodes=[this.documentElement],this.nodeType=9}var W=Ue.prototype;W.createTextNode=function(e){return new di(e,this)};W.createElementNS=function(e,t){var i=e===null?null:String(e);return new Re(t,this,i)};W.createElement=function(e){return new Re(e,this)};W.createDocumentFragment=function(){return new li(this)};W.createEvent=function(e){return new ci(e)};W.createComment=function(e){return new ui(e,this)};W.getElementById=function(e){e=String(e);var t=si(this.childNodes,function(i){if(String(i.id)===e)return i});return t||null};W.getElementsByClassName=Re.prototype.getElementsByClassName;W.getElementsByTagName=Re.prototype.getElementsByTagName;W.contains=Re.prototype.contains;W.removeEventListener=pi;W.addEventListener=fi;W.dispatchEvent=_i});var Cr=B(function(Uu,Lr){var vi=Nr();Lr.exports=new vi});var Br=B(function(Fu,Hr){var Mr=typeof global!=\"undefined\"?global:typeof window!=\"undefined\"?window:{},mi=Cr(),qe;typeof document!=\"undefined\"?qe=document:(qe=Mr[\"__GLOBAL_DOCUMENT_CACHE@4\"],qe||(qe=Mr[\"__GLOBAL_DOCUMENT_CACHE@4\"]=mi));Hr.exports=qe});function ft(r){if(Array.isArray(r))return r}function pt(r,e){var t=r==null?null:typeof Symbol!=\"undefined\"&&r[Symbol.iterator]||r[\"@@iterator\"];if(t!=null){var i=[],a=!0,n=!1,o,s;try{for(t=t.call(r);!(a=(o=t.next()).done)&&(i.push(o.value),!(e&&i.length===e));a=!0);}catch(u){n=!0,s=u}finally{try{!a&&t.return!=null&&t.return()}finally{if(n)throw s}}return i}}function vt(){throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\")}function ke(r,e){(e==null||e>r.length)&&(e=r.length);for(var t=0,i=new Array(e);t<e;t++)i[t]=r[t];return i}function Ae(r,e){if(r){if(typeof r==\"string\")return ke(r,e);var t=Object.prototype.toString.call(r).slice(8,-1);if(t===\"Object\"&&r.constructor&&(t=r.constructor.name),t===\"Map\"||t===\"Set\")return Array.from(t);if(t===\"Arguments\"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t))return ke(r,e)}}function H(r,e){return ft(r)||pt(r,e)||Ae(r,e)||vt()}var be=J(Q());var ee=function(){return\"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g,function(e){var t=Math.random()*16|0,i=e===\"x\"?t:t&3|8;return i.toString(16)})},Oe=function(){return(\"000000\"+(Math.random()*Math.pow(36,6)<<0).toString(36)).slice(-6)};var G=function(e){if(e&&typeof e.nodeName!=\"undefined\")return e.muxId||(e.muxId=Oe()),e.muxId;var t;try{t=document.querySelector(e)}catch(i){}return t&&!t.muxId&&(t.muxId=e),(t==null?void 0:t.muxId)||e},se=function(e){var t;e&&typeof e.nodeName!=\"undefined\"?(t=e,e=G(t)):t=document.querySelector(e);var i=t&&t.nodeName?t.nodeName.toLowerCase():\"\";return[t,e,i]};function ht(r){if(Array.isArray(r))return ke(r)}function yt(r){if(typeof Symbol!=\"undefined\"&&r[Symbol.iterator]!=null||r[\"@@iterator\"]!=null)return Array.from(r)}function gt(){throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\")}function V(r){return ht(r)||yt(r)||Ae(r)||gt()}var Y={TRACE:0,DEBUG:1,INFO:2,WARN:3,ERROR:4,SILENT:5},bt=function(r){var e=arguments.length>1&&arguments[1]!==void 0?arguments[1]:3,t,i,a,n,o,s=r?[console,r]:[console],u=(t=console.trace).bind.apply(t,V(s)),v=(i=console.info).bind.apply(i,V(s)),w=(a=console.debug).bind.apply(a,V(s)),k=(n=console.warn).bind.apply(n,V(s)),y=(o=console.error).bind.apply(o,V(s)),c=e;return{trace:function(){for(var b=arguments.length,x=new Array(b),m=0;m<b;m++)x[m]=arguments[m];if(!(c>Y.TRACE))return u.apply(void 0,V(x))},debug:function(){for(var b=arguments.length,x=new Array(b),m=0;m<b;m++)x[m]=arguments[m];if(!(c>Y.DEBUG))return w.apply(void 0,V(x))},info:function(){for(var b=arguments.length,x=new Array(b),m=0;m<b;m++)x[m]=arguments[m];if(!(c>Y.INFO))return v.apply(void 0,V(x))},warn:function(){for(var b=arguments.length,x=new Array(b),m=0;m<b;m++)x[m]=arguments[m];if(!(c>Y.WARN))return k.apply(void 0,V(x))},error:function(){for(var b=arguments.length,x=new Array(b),m=0;m<b;m++)x[m]=arguments[m];if(!(c>Y.ERROR))return y.apply(void 0,V(x))},get level(){return c},set level(p){p!==this.level&&(c=p!=null?p:e)}}};var q=bt(\"[mux]\");var Ie=J(Q());function ce(){var r=Ie.default.doNotTrack||Ie.default.navigator&&Ie.default.navigator.doNotTrack;return r===\"1\"}var Tt=J(Q()),ea={now:function(){var r=Tt.default.performance,e=r&&r.timing,t=e&&e.navigationStart,i=typeof t==\"number\"&&typeof r.now==\"function\"?t+r.now():Date.now();return Math.round(i)}},A=ea;function g(r){if(r===void 0)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return r}te();function D(r,e){if(!U(r,e))throw new TypeError(\"Cannot call a class as a function\")}function wt(r,e){for(var t=0;t<e.length;t++){var i=e[t];i.enumerable=i.enumerable||!1,i.configurable=!0,\"value\"in i&&(i.writable=!0),Object.defineProperty(r,i.key,i)}}function L(r,e,t){return e&&wt(r.prototype,e),t&&wt(r,t),r}function l(r,e,t){return e in r?Object.defineProperty(r,e,{value:t,enumerable:!0,configurable:!0,writable:!0}):r[e]=t,r}function X(r){return X=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)},X(r)}function Et(r,e){for(;!Object.prototype.hasOwnProperty.call(r,e)&&(r=X(r),r!==null););return r}function De(r,e,t){return typeof Reflect!=\"undefined\"&&Reflect.get?De=Reflect.get:De=function(a,n,o){var s=Et(a,n);if(s){var u=Object.getOwnPropertyDescriptor(s,n);return u.get?u.get.call(o||a):u.value}},De(r,e,t||r)}function Pe(r,e){return Pe=Object.setPrototypeOf||function(i,a){return i.__proto__=a,i},Pe(r,e)}function kt(r,e){if(typeof e!=\"function\"&&e!==null)throw new TypeError(\"Super expression must either be null or a function\");r.prototype=Object.create(e&&e.prototype,{constructor:{value:r,writable:!0,configurable:!0}}),e&&Pe(r,e)}function xt(){if(typeof Reflect==\"undefined\"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy==\"function\")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch(r){return!1}}Ge();function Dt(r,e){return e&&(Ne(e)===\"object\"||typeof e==\"function\")?e:g(r)}function St(r){var e=xt();return function(){var i=X(r),a;if(e){var n=X(this).constructor;a=Reflect.construct(i,arguments,n)}else a=i.apply(this,arguments);return Dt(this,a)}}var F=function(r){return re(r)[0]};var re=function(r){if(typeof r!=\"string\"||r===\"\")return[\"localhost\"];var e=/^(([^:\\/?#]+):)?(\\/\\/([^\\/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?/,t=r.match(e)||[],i=t[4],a;return i&&(a=(i.match(/[^\\.]+\\.[^\\.]+$/)||[])[0]),[i,a]};var Le=J(Q()),ta={exists:function(){var r=Le.default.performance,e=r&&r.timing;return e!==void 0},domContentLoadedEventEnd:function(){var r=Le.default.performance,e=r&&r.timing;return e&&e.domContentLoadedEventEnd},navigationStart:function(){var r=Le.default.performance,e=r&&r.timing;return e&&e.navigationStart}},_e=ta;function O(r,e,t){t=t===void 0?1:t,r[e]=r[e]||0,r[e]+=t}function ue(r){for(var e=1;e<arguments.length;e++){var t=arguments[e]!=null?arguments[e]:{},i=Object.keys(t);typeof Object.getOwnPropertySymbols==\"function\"&&(i=i.concat(Object.getOwnPropertySymbols(t).filter(function(a){return Object.getOwnPropertyDescriptor(t,a).enumerable}))),i.forEach(function(a){l(r,a,t[a])})}return r}function ra(r,e){var t=Object.keys(r);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(r);e&&(i=i.filter(function(a){return Object.getOwnPropertyDescriptor(r,a).enumerable})),t.push.apply(t,i)}return t}function fe(r,e){return e=e!=null?e:{},Object.getOwnPropertyDescriptors?Object.defineProperties(r,Object.getOwnPropertyDescriptors(e)):ra(Object(e)).forEach(function(t){Object.defineProperty(r,t,Object.getOwnPropertyDescriptor(e,t))}),r}var aa=[\"x-cdn\",\"content-type\"],Rt=[\"x-request-id\",\"cf-ray\",\"x-amz-cf-id\",\"x-akamai-request-id\"],ia=aa.concat(Rt);function pe(r){r=r||\"\";var e={},t=r.trim().split(/[\\r\\n]+/);return t.forEach(function(i){if(i){var a=i.split(\": \"),n=a.shift();n&&(ia.indexOf(n.toLowerCase())>=0||n.toLowerCase().indexOf(\"x-litix-\")===0)&&(e[n]=a.join(\": \"))}}),e}function de(r){if(r){var e=Rt.find(function(t){return r[t]!==void 0});return e?r[e]:void 0}}var na=function(r){var e={};for(var t in r){var i=r[t],a=i[\"DATA-ID\"].search(\"io.litix.data.\");if(a!==-1){var n=i[\"DATA-ID\"].replace(\"io.litix.data.\",\"\");e[n]=i.VALUE}}return e},Ce=na;var Me=function(r){if(!r)return{};var e=_e.navigationStart(),t=r.loading,i=t?t.start:r.trequest,a=t?t.first:r.tfirst,n=t?t.end:r.tload;return{bytesLoaded:r.total,requestStart:Math.round(e+i),responseStart:Math.round(e+a),responseEnd:Math.round(e+n)}},Se=function(r){if(!(!r||typeof r.getAllResponseHeaders!=\"function\"))return pe(r.getAllResponseHeaders())},qt=function(r,e,t){var i=arguments.length>3&&arguments[3]!==void 0?arguments[3]:{},a=arguments.length>4?arguments[4]:void 0,n=r.log,o=r.utils.secondsToMs,s=function(m){var f=parseInt(a.version),_;return f===1&&m.programDateTime!==null&&(_=m.programDateTime),f===0&&m.pdt!==null&&(_=m.pdt),_};if(!_e.exists()){n.warn(\"performance timing not supported. Not tracking HLS.js.\");return}var u=function(m,f){return r.emit(e,m,f)},v=function(m,f){var _=f.levels,d=f.audioTracks,h=f.url,T=f.stats,E=f.networkDetails,S=f.sessionData,N={},M={};_.forEach(function(j,oe){N[oe]={width:j.width,height:j.height,bitrate:j.bitrate,attrs:j.attrs}}),d.forEach(function(j,oe){M[oe]={name:j.name,language:j.lang,bitrate:j.bitrate}});var I=Me(T),R=I.bytesLoaded,Z=I.requestStart,Te=I.responseStart,we=I.responseEnd;u(\"requestcompleted\",fe(ue({},Ce(S)),{request_event_type:m,request_bytes_loaded:R,request_start:Z,request_response_start:Te,request_response_end:we,request_type:\"manifest\",request_hostname:F(h),request_response_headers:Se(E),request_rendition_lists:{media:N,audio:M,video:{}}}))};t.on(a.Events.MANIFEST_LOADED,v);var w=function(m,f){var _=f.details,d=f.level,h=f.networkDetails,T=f.stats,E=Me(T),S=E.bytesLoaded,N=E.requestStart,M=E.responseStart,I=E.responseEnd,R=_.fragments[_.fragments.length-1],Z=s(R)+o(R.duration);u(\"requestcompleted\",{request_event_type:m,request_bytes_loaded:S,request_start:N,request_response_start:M,request_response_end:I,request_current_level:d,request_type:\"manifest\",request_hostname:F(_.url),request_response_headers:Se(h),video_holdback:_.holdBack&&o(_.holdBack),video_part_holdback:_.partHoldBack&&o(_.partHoldBack),video_part_target_duration:_.partTarget&&o(_.partTarget),video_target_duration:_.targetduration&&o(_.targetduration),video_source_is_live:_.live,player_manifest_newest_program_time:isNaN(Z)?void 0:Z})};t.on(a.Events.LEVEL_LOADED,w);var k=function(m,f){var _=f.details,d=f.networkDetails,h=f.stats,T=Me(h),E=T.bytesLoaded,S=T.requestStart,N=T.responseStart,M=T.responseEnd;u(\"requestcompleted\",{request_event_type:m,request_bytes_loaded:E,request_start:S,request_response_start:N,request_response_end:M,request_type:\"manifest\",request_hostname:F(_.url),request_response_headers:Se(d)})};t.on(a.Events.AUDIO_TRACK_LOADED,k);var y=function(m,f){var _=f.stats,d=f.networkDetails,h=f.frag;_=_||h.stats;var T=Me(_),E=T.bytesLoaded,S=T.requestStart,N=T.responseStart,M=T.responseEnd,I=d?Se(d):void 0,R={request_event_type:m,request_bytes_loaded:E,request_start:S,request_response_start:N,request_response_end:M,request_hostname:d?F(d.responseURL):void 0,request_id:I?de(I):void 0,request_response_headers:I,request_media_duration:h.duration,request_url:d==null?void 0:d.responseURL};h.type===\"main\"?(R.request_type=\"media\",R.request_current_level=h.level,R.request_video_width=(t.levels[h.level]||{}).width,R.request_video_height=(t.levels[h.level]||{}).height,R.request_labeled_bitrate=(t.levels[h.level]||{}).bitrate):R.request_type=h.type,u(\"requestcompleted\",R)};t.on(a.Events.FRAG_LOADED,y);var c=function(m,f){var _=f.frag,d=_.start,h=s(_),T={currentFragmentPDT:h,currentFragmentStart:o(d)};u(\"fragmentchange\",T)};t.on(a.Events.FRAG_CHANGED,c);var p=function(m,f){var _=f.type,d=f.details,h=f.response,T=f.fatal,E=f.frag,S=f.networkDetails,N=(E==null?void 0:E.url)||f.url||\"\",M=S?Se(S):void 0;if((d===a.ErrorDetails.MANIFEST_LOAD_ERROR||d===a.ErrorDetails.MANIFEST_LOAD_TIMEOUT||d===a.ErrorDetails.FRAG_LOAD_ERROR||d===a.ErrorDetails.FRAG_LOAD_TIMEOUT||d===a.ErrorDetails.LEVEL_LOAD_ERROR||d===a.ErrorDetails.LEVEL_LOAD_TIMEOUT||d===a.ErrorDetails.AUDIO_TRACK_LOAD_ERROR||d===a.ErrorDetails.AUDIO_TRACK_LOAD_TIMEOUT||d===a.ErrorDetails.SUBTITLE_LOAD_ERROR||d===a.ErrorDetails.SUBTITLE_LOAD_TIMEOUT||d===a.ErrorDetails.KEY_LOAD_ERROR||d===a.ErrorDetails.KEY_LOAD_TIMEOUT)&&u(\"requestfailed\",{request_error:d,request_url:N,request_hostname:F(N),request_id:M?de(M):void 0,request_type:d===a.ErrorDetails.FRAG_LOAD_ERROR||d===a.ErrorDetails.FRAG_LOAD_TIMEOUT?\"media\":d===a.ErrorDetails.AUDIO_TRACK_LOAD_ERROR||d===a.ErrorDetails.AUDIO_TRACK_LOAD_TIMEOUT?\"audio\":d===a.ErrorDetails.SUBTITLE_LOAD_ERROR||d===a.ErrorDetails.SUBTITLE_LOAD_TIMEOUT?\"subtitle\":d===a.ErrorDetails.KEY_LOAD_ERROR||d===a.ErrorDetails.KEY_LOAD_TIMEOUT?\"encryption\":\"manifest\",request_error_code:h==null?void 0:h.code,request_error_text:h==null?void 0:h.text}),T){var I,R=\"\".concat(N?\"url: \".concat(N,\"\\n\"):\"\")+\"\".concat(h&&(h.code||h.text)?\"response: \".concat(h.code,\", \").concat(h.text,\"\\n\"):\"\")+\"\".concat(f.reason?\"failure reason: \".concat(f.reason,\"\\n\"):\"\")+\"\".concat(f.level?\"level: \".concat(f.level,\"\\n\"):\"\")+\"\".concat(f.parent?\"parent stream controller: \".concat(f.parent,\"\\n\"):\"\")+\"\".concat(f.buffer?\"buffer length: \".concat(f.buffer,\"\\n\"):\"\")+\"\".concat(f.error?\"error: \".concat(f.error,\"\\n\"):\"\")+\"\".concat(f.event?\"event: \".concat(f.event,\"\\n\"):\"\")+\"\".concat(f.err?\"error message: \".concat((I=f.err)===null||I===void 0?void 0:I.message,\"\\n\"):\"\");u(\"error\",{player_error_code:_,player_error_message:d,player_error_context:R})}};t.on(a.Events.ERROR,p);var b=function(m,f){var _=f.frag,d=_&&_._url||\"\";u(\"requestcanceled\",{request_event_type:m,request_url:d,request_type:\"media\",request_hostname:F(d)})};t.on(a.Events.FRAG_LOAD_EMERGENCY_ABORTED,b);var x=function(m,f){var _=f.level,d=t.levels[_];if(d&&d.attrs&&d.attrs.BANDWIDTH){var h=d.attrs.BANDWIDTH,T,E=parseFloat(d.attrs[\"FRAME-RATE\"]);isNaN(E)||(T=E),h?u(\"renditionchange\",{video_source_fps:T,video_source_bitrate:h,video_source_width:d.width,video_source_height:d.height,video_source_rendition_name:d.name,video_source_codec:d==null?void 0:d.videoCodec}):n.warn(\"missing BANDWIDTH from HLS manifest parsed by HLS.js\")}};t.on(a.Events.LEVEL_SWITCHED,x),t._stopMuxMonitor=function(){t.off(a.Events.MANIFEST_LOADED,v),t.off(a.Events.LEVEL_LOADED,w),t.off(a.Events.AUDIO_TRACK_LOADED,k),t.off(a.Events.FRAG_LOADED,y),t.off(a.Events.FRAG_CHANGED,c),t.off(a.Events.ERROR,p),t.off(a.Events.FRAG_LOAD_EMERGENCY_ABORTED,b),t.off(a.Events.LEVEL_SWITCHED,x),t.off(a.Events.DESTROYING,t._stopMuxMonitor),delete t._stopMuxMonitor},t.on(a.Events.DESTROYING,t._stopMuxMonitor)},At=function(r){r&&typeof r._stopMuxMonitor==\"function\"&&r._stopMuxMonitor()};var Ot=function(r,e){if(!r||!r.requestEndDate)return{};var t=F(r.url),i=r.url,a=r.bytesLoaded,n=new Date(r.requestStartDate).getTime(),o=new Date(r.firstByteDate).getTime(),s=new Date(r.requestEndDate).getTime(),u=isNaN(r.duration)?0:r.duration,v=typeof e.getMetricsFor==\"function\"?e.getMetricsFor(r.mediaType).HttpList:e.getDashMetrics().getHttpRequests(r.mediaType),w;v.length>0&&(w=pe(v[v.length-1]._responseHeaders||\"\"));var k=w?de(w):void 0;return{requestStart:n,requestResponseStart:o,requestResponseEnd:s,requestBytesLoaded:a,requestResponseHeaders:w,requestMediaDuration:u,requestHostname:t,requestUrl:i,requestId:k}},oa=function(r,e){var t=e.getQualityFor(r),i=e.getCurrentTrackFor(r).bitrateList;return i?{currentLevel:t,renditionWidth:i[t].width||null,renditionHeight:i[t].height||null,renditionBitrate:i[t].bandwidth}:{}},sa=function(r){var e;return(e=r.match(/.*codecs\\*?=\"(.*)\"/))===null||e===void 0?void 0:e[1]},ua=function(e){try{var t,i,a=(i=e.getVersion)===null||i===void 0||(t=i.call(e))===null||t===void 0?void 0:t.split(\".\").map(function(n){return parseInt(n)})[0];return a}catch(n){return!1}},It=function(r,e,t){var i=arguments.length>3&&arguments[3]!==void 0?arguments[3]:{},a=r.log;if(!t||!t.on){a.warn(\"Invalid dash.js player reference. Monitoring blocked.\");return}var n=ua(t),o=function(_,d){return r.emit(e,_,d)},s=function(_){var d=_.type,h=_.data,T=(h||{}).url;o(\"requestcompleted\",{request_event_type:d,request_start:0,request_response_start:0,request_response_end:0,request_bytes_loaded:-1,request_type:\"manifest\",request_hostname:F(T),request_url:T})};t.on(\"manifestLoaded\",s);var u={},v=function(_){if(typeof _.getRequests!=\"function\")return null;var d=_.getRequests({state:\"executed\"});return d.length===0?null:d[d.length-1]},w=function(_){var d=_.type,h=_.fragmentModel,T=_.chunk,E=v(h);k({type:d,request:E,chunk:T})},k=function(_){var d=_.type,h=_.chunk,T=_.request,E=(h||{}).mediaInfo,S=E||{},N=S.type,M=S.bitrateList;M=M||[];var I={};M.forEach(function(Ee,z){I[z]={},I[z].width=Ee.width,I[z].height=Ee.height,I[z].bitrate=Ee.bandwidth,I[z].attrs={}}),N===\"video\"?u.video=I:N===\"audio\"?u.audio=I:u.media=I;var R=Ot(T,t),Z=R.requestStart,Te=R.requestResponseStart,we=R.requestResponseEnd,j=R.requestResponseHeaders,oe=R.requestMediaDuration,Ve=R.requestHostname,We=R.requestUrl,je=R.requestId;o(\"requestcompleted\",{request_event_type:d,request_start:Z,request_response_start:Te,request_response_end:we,request_bytes_loaded:-1,request_type:N+\"_init\",request_response_headers:j,request_hostname:Ve,request_id:je,request_url:We,request_media_duration:oe,request_rendition_lists:u})};n>=4?t.on(\"initFragmentLoaded\",k):t.on(\"initFragmentLoaded\",w);var y=function(_){var d=_.type,h=_.fragmentModel,T=_.chunk,E=v(h);c({type:d,request:E,chunk:T})},c=function(_){var d=_.type,h=_.chunk,T=_.request,E=h||{},S=E.mediaInfo,N=E.start,M=S||{},I=M.type,R=Ot(T,t),Z=R.requestStart,Te=R.requestResponseStart,we=R.requestResponseEnd,j=R.requestBytesLoaded,oe=R.requestResponseHeaders,Ve=R.requestMediaDuration,We=R.requestHostname,je=R.requestUrl,Ee=R.requestId,z=oa(I,t),jr=z.currentLevel,Gr=z.renditionWidth,Jr=z.renditionHeight,Qr=z.renditionBitrate;o(\"requestcompleted\",{request_event_type:d,request_start:Z,request_response_start:Te,request_response_end:we,request_bytes_loaded:j,request_type:I,request_response_headers:oe,request_hostname:We,request_id:Ee,request_url:je,request_media_start_time:N,request_media_duration:Ve,request_current_level:jr,request_labeled_bitrate:Qr,request_video_width:Gr,request_video_height:Jr})};n>=4?t.on(\"mediaFragmentLoaded\",c):t.on(\"mediaFragmentLoaded\",y);var p={video:void 0,audio:void 0,totalBitrate:void 0},b=function(){if(p.video&&typeof p.video.bitrate==\"number\"){if(!(p.video.width&&p.video.height)){a.warn(\"have bitrate info for video but missing width/height\");return}var _=p.video.bitrate;if(p.audio&&typeof p.audio.bitrate==\"number\"&&(_+=p.audio.bitrate),_!==p.totalBitrate)return p.totalBitrate=_,{video_source_bitrate:_,video_source_height:p.video.height,video_source_width:p.video.width,video_source_codec:sa(p.video.codec)}}},x=function(_,d,h){if(typeof _.newQuality!=\"number\"){a.warn(\"missing evt.newQuality in qualityChangeRendered event\",_);return}var T=_.mediaType;if(T===\"audio\"||T===\"video\"){var E=t.getBitrateInfoListFor(T).find(function(N){var M=N.qualityIndex;return M===_.newQuality});if(!(E&&typeof E.bitrate==\"number\")){a.warn(\"missing bitrate info for \".concat(T));return}p[T]=fe(ue({},E),{codec:t.getCurrentTrackFor(T).codec});var S=b();S&&o(\"renditionchange\",S)}};t.on(\"qualityChangeRendered\",x);var m=function(_){var d=_.request,h=_.mediaType;d=d||{},o(\"requestcanceled\",{request_event_type:d.type+\"_\"+d.action,request_url:d.url,request_type:h,request_hostname:F(d.url)})};t.on(\"fragmentLoadingAbandoned\",m);var f=function(_){var d=_.error,h,T,E=(d==null||(h=d.data)===null||h===void 0?void 0:h.request)||{},S=(d==null||(T=d.data)===null||T===void 0?void 0:T.response)||{};(d==null?void 0:d.code)===27&&o(\"requestfailed\",{request_error:E.type+\"_\"+E.action,request_url:E.url,request_hostname:F(E.url),request_type:E.mediaType,request_error_code:S.status,request_error_text:S.statusText});var N=\"\".concat(E!=null&&E.url?\"url: \".concat(E.url,\"\\n\"):\"\")+\"\".concat(S!=null&&S.status||S!=null&&S.statusText?\"response: \".concat(S==null?void 0:S.status,\", \").concat(S==null?void 0:S.statusText,\"\\n\"):\"\");o(\"error\",{player_error_code:d==null?void 0:d.code,player_error_message:d==null?void 0:d.message,player_error_context:N})};t.on(\"error\",f),t._stopMuxMonitor=function(){t.off(\"manifestLoaded\",s),t.off(\"initFragmentLoaded\",k),t.off(\"mediaFragmentLoaded\",c),t.off(\"qualityChangeRendered\",x),t.off(\"error\",f),t.off(\"fragmentLoadingAbandoned\",m),delete t._stopMuxMonitor}},Pt=function(r){r&&typeof r._stopMuxMonitor==\"function\"&&r._stopMuxMonitor()};var Nt=0,da=function(){\"use strict\";function r(){D(this,r),l(this,\"_listeners\",void 0)}return L(r,[{key:\"on\",value:function(t,i,a){return i._eventEmitterGuid=i._eventEmitterGuid||++Nt,this._listeners=this._listeners||{},this._listeners[t]=this._listeners[t]||[],a&&(i=i.bind(a)),this._listeners[t].push(i),i}},{key:\"off\",value:function(t,i){var a=this._listeners&&this._listeners[t];a&&a.forEach(function(n,o){n._eventEmitterGuid===i._eventEmitterGuid&&a.splice(o,1)})}},{key:\"one\",value:function(t,i,a){var n=this;i._eventEmitterGuid=i._eventEmitterGuid||++Nt;var o=function(){n.off(t,o),i.apply(a||this,arguments)};o._eventEmitterGuid=i._eventEmitterGuid,this.on(t,o)}},{key:\"emit\",value:function(t,i){var a=this;if(this._listeners){i=i||{};var n=this._listeners[\"before*\"]||[],o=this._listeners[t]||[],s=this._listeners[\"after\"+t]||[],u=function(v,w){v=v.slice(),v.forEach(function(k){k.call(a,{type:t},w)})};u(n,i),u(o,i),u(s,i)}}}]),r}(),Lt=da;var He=J(Q()),la=function(){\"use strict\";function r(e){var t=this;D(this,r),l(this,\"_playbackHeartbeatInterval\",void 0),l(this,\"_playheadShouldBeProgressing\",void 0),l(this,\"pm\",void 0),this.pm=e,this._playbackHeartbeatInterval=null,this._playheadShouldBeProgressing=!1,e.on(\"playing\",function(){t._playheadShouldBeProgressing=!0}),e.on(\"play\",this._startPlaybackHeartbeatInterval.bind(this)),e.on(\"playing\",this._startPlaybackHeartbeatInterval.bind(this)),e.on(\"adbreakstart\",this._startPlaybackHeartbeatInterval.bind(this)),e.on(\"adplay\",this._startPlaybackHeartbeatInterval.bind(this)),e.on(\"adplaying\",this._startPlaybackHeartbeatInterval.bind(this)),e.on(\"devicewake\",this._startPlaybackHeartbeatInterval.bind(this)),e.on(\"viewstart\",this._startPlaybackHeartbeatInterval.bind(this)),e.on(\"rebufferstart\",this._startPlaybackHeartbeatInterval.bind(this)),e.on(\"pause\",this._stopPlaybackHeartbeatInterval.bind(this)),e.on(\"ended\",this._stopPlaybackHeartbeatInterval.bind(this)),e.on(\"viewend\",this._stopPlaybackHeartbeatInterval.bind(this)),e.on(\"error\",this._stopPlaybackHeartbeatInterval.bind(this)),e.on(\"aderror\",this._stopPlaybackHeartbeatInterval.bind(this)),e.on(\"adpause\",this._stopPlaybackHeartbeatInterval.bind(this)),e.on(\"adended\",this._stopPlaybackHeartbeatInterval.bind(this)),e.on(\"adbreakend\",this._stopPlaybackHeartbeatInterval.bind(this)),e.on(\"seeked\",function(){e.data.player_is_paused?t._stopPlaybackHeartbeatInterval():t._startPlaybackHeartbeatInterval()}),e.on(\"timeupdate\",function(){t._playbackHeartbeatInterval!==null&&e.emit(\"playbackheartbeat\")}),e.on(\"devicesleep\",function(i,a){t._playbackHeartbeatInterval!==null&&(He.default.clearInterval(t._playbackHeartbeatInterval),e.emit(\"playbackheartbeatend\",{viewer_time:a.viewer_time}),t._playbackHeartbeatInterval=null)})}return L(r,[{key:\"_startPlaybackHeartbeatInterval\",value:function(){var t=this;this._playbackHeartbeatInterval===null&&(this.pm.emit(\"playbackheartbeat\"),this._playbackHeartbeatInterval=He.default.setInterval(function(){t.pm.emit(\"playbackheartbeat\")},this.pm.playbackHeartbeatTime))}},{key:\"_stopPlaybackHeartbeatInterval\",value:function(){this._playheadShouldBeProgressing=!1,this._playbackHeartbeatInterval!==null&&(He.default.clearInterval(this._playbackHeartbeatInterval),this.pm.emit(\"playbackheartbeatend\"),this._playbackHeartbeatInterval=null)}}]),r}(),Ct=la;var ca=function r(e){\"use strict\";var t=this;D(this,r),l(this,\"viewErrored\",void 0),e.on(\"viewinit\",function(){t.viewErrored=!1}),e.on(\"error\",function(i,a){try{var n=e.errorTranslator({player_error_code:a.player_error_code,player_error_message:a.player_error_message,player_error_context:a.player_error_context,player_error_severity:a.player_error_severity,player_error_business_exception:a.player_error_business_exception});n&&(e.data.player_error_code=n.player_error_code||a.player_error_code,e.data.player_error_message=n.player_error_message||a.player_error_message,e.data.player_error_context=n.player_error_context||a.player_error_context,e.data.player_error_severity=n.player_error_severity||a.player_error_severity,e.data.player_error_business_exception=n.player_error_business_exception||a.player_error_business_exception,t.viewErrored=!0)}catch(o){e.mux.log.warn(\"Exception in error translator callback.\",o),t.viewErrored=!0}}),e.on(\"aftererror\",function(){var i,a,n,o,s;(i=e.data)===null||i===void 0||delete i.player_error_code,(a=e.data)===null||a===void 0||delete a.player_error_message,(n=e.data)===null||n===void 0||delete n.player_error_context,(o=e.data)===null||o===void 0||delete o.player_error_severity,(s=e.data)===null||s===void 0||delete s.player_error_business_exception})},Mt=ca;var _a=function(){\"use strict\";function r(e){D(this,r),l(this,\"_watchTimeTrackerLastCheckedTime\",void 0),l(this,\"pm\",void 0),this.pm=e,this._watchTimeTrackerLastCheckedTime=null,e.on(\"playbackheartbeat\",this._updateWatchTime.bind(this)),e.on(\"playbackheartbeatend\",this._clearWatchTimeState.bind(this))}return L(r,[{key:\"_updateWatchTime\",value:function(t,i){var a=i.viewer_time;this._watchTimeTrackerLastCheckedTime===null&&(this._watchTimeTrackerLastCheckedTime=a),O(this.pm.data,\"view_watch_time\",a-this._watchTimeTrackerLastCheckedTime),this._watchTimeTrackerLastCheckedTime=a}},{key:\"_clearWatchTimeState\",value:function(t,i){this._updateWatchTime(t,i),this._watchTimeTrackerLastCheckedTime=null}}]),r}(),Ht=_a;var fa=function(){\"use strict\";function r(e){var t=this;D(this,r),l(this,\"_playbackTimeTrackerLastPlayheadPosition\",void 0),l(this,\"_lastTime\",void 0),l(this,\"_isAdPlaying\",void 0),l(this,\"_callbackUpdatePlaybackTime\",void 0),l(this,\"pm\",void 0),this.pm=e,this._playbackTimeTrackerLastPlayheadPosition=-1,this._lastTime=A.now(),this._isAdPlaying=!1,this._callbackUpdatePlaybackTime=null;var i=this._startPlaybackTimeTracking.bind(this);e.on(\"playing\",i),e.on(\"adplaying\",i),e.on(\"seeked\",i);var a=this._stopPlaybackTimeTracking.bind(this);e.on(\"playbackheartbeatend\",a),e.on(\"seeking\",a),e.on(\"adplaying\",function(){t._isAdPlaying=!0}),e.on(\"adended\",function(){t._isAdPlaying=!1}),e.on(\"adpause\",function(){t._isAdPlaying=!1}),e.on(\"adbreakstart\",function(){t._isAdPlaying=!1}),e.on(\"adbreakend\",function(){t._isAdPlaying=!1}),e.on(\"adplay\",function(){t._isAdPlaying=!1}),e.on(\"viewinit\",function(){t._playbackTimeTrackerLastPlayheadPosition=-1,t._lastTime=A.now(),t._isAdPlaying=!1,t._callbackUpdatePlaybackTime=null})}return L(r,[{key:\"_startPlaybackTimeTracking\",value:function(){this._callbackUpdatePlaybackTime===null&&(this._callbackUpdatePlaybackTime=this._updatePlaybackTime.bind(this),this._playbackTimeTrackerLastPlayheadPosition=this.pm.data.player_playhead_time,this.pm.on(\"playbackheartbeat\",this._callbackUpdatePlaybackTime))}},{key:\"_stopPlaybackTimeTracking\",value:function(){this._callbackUpdatePlaybackTime&&(this._updatePlaybackTime(),this.pm.off(\"playbackheartbeat\",this._callbackUpdatePlaybackTime),this._callbackUpdatePlaybackTime=null,this._playbackTimeTrackerLastPlayheadPosition=-1)}},{key:\"_updatePlaybackTime\",value:function(){var t=this.pm.data.player_playhead_time,i=A.now(),a=-1;this._playbackTimeTrackerLastPlayheadPosition>=0&&t>this._playbackTimeTrackerLastPlayheadPosition?a=t-this._playbackTimeTrackerLastPlayheadPosition:this._isAdPlaying&&(a=i-this._lastTime),a>0&&a<=1e3&&O(this.pm.data,\"view_content_playback_time\",a),this._playbackTimeTrackerLastPlayheadPosition=t,this._lastTime=i}}]),r}(),Bt=fa;var pa=function(){\"use strict\";function r(e){D(this,r),l(this,\"pm\",void 0),this.pm=e;var t=this._updatePlayheadTime.bind(this);e.on(\"playbackheartbeat\",t),e.on(\"playbackheartbeatend\",t),e.on(\"timeupdate\",t),e.on(\"destroy\",function(){e.off(\"timeupdate\",t)})}return L(r,[{key:\"_updateMaxPlayheadPosition\",value:function(){this.pm.data.view_max_playhead_position=typeof this.pm.data.view_max_playhead_position==\"undefined\"?this.pm.data.player_playhead_time:Math.max(this.pm.data.view_max_playhead_position,this.pm.data.player_playhead_time)}},{key:\"_updatePlayheadTime\",value:function(t,i){var a=this,n=function(){a.pm.currentFragmentPDT&&a.pm.currentFragmentStart&&(a.pm.data.player_program_time=a.pm.currentFragmentPDT+a.pm.data.player_playhead_time-a.pm.currentFragmentStart)};if(i&&i.player_playhead_time)this.pm.data.player_playhead_time=i.player_playhead_time,n(),this._updateMaxPlayheadPosition();else if(this.pm.getPlayheadTime){var o=this.pm.getPlayheadTime();typeof o!=\"undefined\"&&(this.pm.data.player_playhead_time=o,n(),this._updateMaxPlayheadPosition())}}}]),r}(),Ut=pa;var Ft=5*60*1e3,va=function r(e){\"use strict\";if(D(this,r),!e.disableRebufferTracking){var t,i=function(n,o){a(o),t=void 0},a=function(n){if(t){var o=n.viewer_time-t;O(e.data,\"view_rebuffer_duration\",o),t=n.viewer_time,e.data.view_rebuffer_duration>Ft&&(e.emit(\"viewend\"),e.send(\"viewend\"),e.mux.log.warn(\"Ending view after rebuffering for longer than \".concat(Ft,\"ms, future events will be ignored unless a programchange or videochange occurs.\")))}e.data.view_watch_time>=0&&e.data.view_rebuffer_count>0&&(e.data.view_rebuffer_frequency=e.data.view_rebuffer_count/e.data.view_watch_time,e.data.view_rebuffer_percentage=e.data.view_rebuffer_duration/e.data.view_watch_time)};e.on(\"playbackheartbeat\",function(n,o){return a(o)}),e.on(\"rebufferstart\",function(n,o){t||(O(e.data,\"view_rebuffer_count\",1),t=o.viewer_time,e.one(\"rebufferend\",i))}),e.on(\"viewinit\",function(){t=void 0,e.off(\"rebufferend\",i)})}},Vt=va;var ma=function(){\"use strict\";function r(e){var t=this;D(this,r),l(this,\"_lastCheckedTime\",void 0),l(this,\"_lastPlayheadTime\",void 0),l(this,\"_lastPlayheadTimeUpdatedTime\",void 0),l(this,\"_rebuffering\",void 0),l(this,\"pm\",void 0),this.pm=e,!(e.disableRebufferTracking||e.disablePlayheadRebufferTracking)&&(this._lastCheckedTime=null,this._lastPlayheadTime=null,this._lastPlayheadTimeUpdatedTime=null,e.on(\"playbackheartbeat\",this._checkIfRebuffering.bind(this)),e.on(\"playbackheartbeatend\",this._cleanupRebufferTracker.bind(this)),e.on(\"seeking\",function(){t._cleanupRebufferTracker(null,{viewer_time:A.now()})}))}return L(r,[{key:\"_checkIfRebuffering\",value:function(t,i){if(this.pm.seekingTracker.isSeeking||this.pm.adTracker.isAdBreak||!this.pm.playbackHeartbeat._playheadShouldBeProgressing){this._cleanupRebufferTracker(t,i);return}if(this._lastCheckedTime===null){this._prepareRebufferTrackerState(i.viewer_time);return}if(this._lastPlayheadTime!==this.pm.data.player_playhead_time){this._cleanupRebufferTracker(t,i,!0);return}var a=i.viewer_time-this._lastPlayheadTimeUpdatedTime;typeof this.pm.sustainedRebufferThreshold==\"number\"&&a>=this.pm.sustainedRebufferThreshold&&(this._rebuffering||(this._rebuffering=!0,this.pm.emit(\"rebufferstart\",{viewer_time:this._lastPlayheadTimeUpdatedTime}))),this._lastCheckedTime=i.viewer_time}},{key:\"_clearRebufferTrackerState\",value:function(){this._lastCheckedTime=null,this._lastPlayheadTime=null,this._lastPlayheadTimeUpdatedTime=null}},{key:\"_prepareRebufferTrackerState\",value:function(t){this._lastCheckedTime=t,this._lastPlayheadTime=this.pm.data.player_playhead_time,this._lastPlayheadTimeUpdatedTime=t}},{key:\"_cleanupRebufferTracker\",value:function(t,i){var a=arguments.length>2&&arguments[2]!==void 0?arguments[2]:!1;if(this._rebuffering)this._rebuffering=!1,this.pm.emit(\"rebufferend\",{viewer_time:i.viewer_time});else{if(this._lastCheckedTime===null)return;var n=this.pm.data.player_playhead_time-this._lastPlayheadTime,o=i.viewer_time-this._lastPlayheadTimeUpdatedTime;typeof this.pm.minimumRebufferDuration==\"number\"&&n>0&&o-n>this.pm.minimumRebufferDuration&&(this._lastCheckedTime=null,this.pm.emit(\"rebufferstart\",{viewer_time:this._lastPlayheadTimeUpdatedTime}),this.pm.emit(\"rebufferend\",{viewer_time:this._lastPlayheadTimeUpdatedTime+o-n}))}a?this._prepareRebufferTrackerState(i.viewer_time):this._clearRebufferTrackerState()}}]),r}(),Wt=ma;var ha=function(){\"use strict\";function r(e){var t=this;D(this,r),l(this,\"NAVIGATION_START\",void 0),l(this,\"pm\",void 0),this.pm=e,e.on(\"viewinit\",function(){var i=e.data,a=i.view_id;if(!i.view_program_changed){var n=function(o,s){var u=s.viewer_time;o.type===\"playing\"&&typeof e.data.view_time_to_first_frame==\"undefined\"?t.calculateTimeToFirstFrame(u||A.now(),a):o.type===\"adplaying\"&&(typeof e.data.view_time_to_first_frame==\"undefined\"||t._inPrerollPosition())&&t.calculateTimeToFirstFrame(u||A.now(),a)};e.one(\"playing\",n),e.one(\"adplaying\",n),e.one(\"viewend\",function(){e.off(\"playing\",n),e.off(\"adplaying\",n)})}})}return L(r,[{key:\"_inPrerollPosition\",value:function(){return typeof this.pm.data.view_content_playback_time==\"undefined\"||this.pm.data.view_content_playback_time<=1e3}},{key:\"calculateTimeToFirstFrame\",value:function(t,i){i===this.pm.data.view_id&&(this.pm.watchTimeTracker._updateWatchTime(null,{viewer_time:t}),this.pm.data.view_time_to_first_frame=this.pm.data.view_watch_time,(this.pm.data.player_autoplay_on||this.pm.data.video_is_autoplay)&&this.NAVIGATION_START&&(this.pm.data.view_aggregate_startup_time=this.pm.data.view_start+this.pm.data.view_watch_time-this.NAVIGATION_START))}}]),r}(),jt=ha;var ya=function r(e){\"use strict\";var t=this;D(this,r),l(this,\"_lastPlayerHeight\",void 0),l(this,\"_lastPlayerWidth\",void 0),l(this,\"_lastPlayheadPosition\",void 0),l(this,\"_lastSourceHeight\",void 0),l(this,\"_lastSourceWidth\",void 0),e.on(\"viewinit\",function(){t._lastPlayheadPosition=-1});var i=[\"pause\",\"rebufferstart\",\"seeking\",\"error\",\"adbreakstart\",\"hb\"],a=[\"playing\",\"hb\"];i.forEach(function(n){e.on(n,function(){if(t._lastPlayheadPosition>=0&&e.data.player_playhead_time>=0&&t._lastPlayerWidth>=0&&t._lastSourceWidth>0&&t._lastPlayerHeight>=0&&t._lastSourceHeight>0){var o=e.data.player_playhead_time-t._lastPlayheadPosition;if(o<0){t._lastPlayheadPosition=-1;return}var s=Math.min(t._lastPlayerWidth/t._lastSourceWidth,t._lastPlayerHeight/t._lastSourceHeight),u=Math.max(0,s-1),v=Math.max(0,1-s);e.data.view_max_upscale_percentage=Math.max(e.data.view_max_upscale_percentage||0,u),e.data.view_max_downscale_percentage=Math.max(e.data.view_max_downscale_percentage||0,v),O(e.data,\"view_total_content_playback_time\",o),O(e.data,\"view_total_upscaling\",u*o),O(e.data,\"view_total_downscaling\",v*o)}t._lastPlayheadPosition=-1})}),a.forEach(function(n){e.on(n,function(){t._lastPlayheadPosition=e.data.player_playhead_time,t._lastPlayerWidth=e.data.player_width,t._lastPlayerHeight=e.data.player_height,t._lastSourceWidth=e.data.video_source_width,t._lastSourceHeight=e.data.video_source_height})})},Gt=ya;var ga=2e3,ba=function r(e){\"use strict\";var t=this;D(this,r),l(this,\"isSeeking\",void 0),this.isSeeking=!1;var i=-1,a=function(){var n=A.now(),o=(e.data.viewer_time||n)-(i||n);O(e.data,\"view_seek_duration\",o),e.data.view_max_seek_time=Math.max(e.data.view_max_seek_time||0,o),t.isSeeking=!1,i=-1};e.on(\"seeking\",function(n,o){if(Object.assign(e.data,o),t.isSeeking&&o.viewer_time-i<=ga){i=o.viewer_time;return}t.isSeeking&&a(),t.isSeeking=!0,i=o.viewer_time,O(e.data,\"view_seek_count\",1),e.send(\"seeking\")}),e.on(\"seeked\",function(){a()}),e.on(\"viewend\",function(){t.isSeeking&&(a(),e.send(\"seeked\")),t.isSeeking=!1,i=-1})},Jt=ba;var Qt=function(e,t){e.push(t),e.sort(function(i,a){return i.viewer_time-a.viewer_time})},Ta=[\"adbreakstart\",\"adrequest\",\"adresponse\",\"adplay\",\"adplaying\",\"adpause\",\"adended\",\"adbreakend\",\"aderror\",\"adclicked\",\"adskipped\"],wa=function(){\"use strict\";function r(e){var t=this;D(this,r),l(this,\"_adHasPlayed\",void 0),l(this,\"_adRequests\",void 0),l(this,\"_adResponses\",void 0),l(this,\"_currentAdRequestNumber\",void 0),l(this,\"_currentAdResponseNumber\",void 0),l(this,\"_prerollPlayTime\",void 0),l(this,\"_wouldBeNewAdPlay\",void 0),l(this,\"isAdBreak\",void 0),l(this,\"pm\",void 0),this.pm=e,e.on(\"viewinit\",function(){t.isAdBreak=!1,t._currentAdRequestNumber=0,t._currentAdResponseNumber=0,t._adRequests=[],t._adResponses=[],t._adHasPlayed=!1,t._wouldBeNewAdPlay=!0,t._prerollPlayTime=void 0}),Ta.forEach(function(a){return e.on(a,t._updateAdData.bind(t))});var i=function(){t.isAdBreak=!1};e.on(\"adbreakstart\",function(){t.isAdBreak=!0}),e.on(\"play\",i),e.on(\"playing\",i),e.on(\"viewend\",i),e.on(\"adrequest\",function(a,n){n=Object.assign({ad_request_id:\"generatedAdRequestId\"+t._currentAdRequestNumber++},n),Qt(t._adRequests,n),O(e.data,\"view_ad_request_count\"),t.inPrerollPosition()&&(e.data.view_preroll_requested=!0,t._adHasPlayed||O(e.data,\"view_preroll_request_count\"))}),e.on(\"adresponse\",function(a,n){n=Object.assign({ad_request_id:\"generatedAdRequestId\"+t._currentAdResponseNumber++},n),Qt(t._adResponses,n);var o=t.findAdRequest(n.ad_request_id);o&&O(e.data,\"view_ad_request_time\",Math.max(0,n.viewer_time-o.viewer_time))}),e.on(\"adplay\",function(a,n){t._adHasPlayed=!0,t._wouldBeNewAdPlay&&(t._wouldBeNewAdPlay=!1,O(e.data,\"view_ad_played_count\")),t.inPrerollPosition()&&!e.data.view_preroll_played&&(e.data.view_preroll_played=!0,t._adRequests.length>0&&(e.data.view_preroll_request_time=Math.max(0,n.viewer_time-t._adRequests[0].viewer_time)),e.data.view_start&&(e.data.view_startup_preroll_request_time=Math.max(0,n.viewer_time-e.data.view_start)),t._prerollPlayTime=n.viewer_time)}),e.on(\"adplaying\",function(a,n){t.inPrerollPosition()&&typeof e.data.view_preroll_load_time==\"undefined\"&&typeof t._prerollPlayTime!=\"undefined\"&&(e.data.view_preroll_load_time=n.viewer_time-t._prerollPlayTime,e.data.view_startup_preroll_load_time=n.viewer_time-t._prerollPlayTime)}),e.on(\"adclicked\",function(a,n){t._wouldBeNewAdPlay||O(e.data,\"view_ad_clicked_count\")}),e.on(\"adskipped\",function(a,n){t._wouldBeNewAdPlay||O(e.data,\"view_ad_skipped_count\")}),e.on(\"adended\",function(){t._wouldBeNewAdPlay=!0}),e.on(\"aderror\",function(){t._wouldBeNewAdPlay=!0})}return L(r,[{key:\"inPrerollPosition\",value:function(){return typeof this.pm.data.view_content_playback_time==\"undefined\"||this.pm.data.view_content_playback_time<=1e3}},{key:\"findAdRequest\",value:function(t){for(var i=0;i<this._adRequests.length;i++)if(this._adRequests[i].ad_request_id===t)return this._adRequests[i]}},{key:\"_updateAdData\",value:function(t,i){if(this.inPrerollPosition()){if(!this.pm.data.view_preroll_ad_tag_hostname&&i.ad_tag_url){var a=H(re(i.ad_tag_url),2),n=a[0],o=a[1];this.pm.data.view_preroll_ad_tag_domain=o,this.pm.data.view_preroll_ad_tag_hostname=n}if(!this.pm.data.view_preroll_ad_asset_hostname&&i.ad_asset_url){var s=H(re(i.ad_asset_url),2),u=s[0],v=s[1];this.pm.data.view_preroll_ad_asset_domain=v,this.pm.data.view_preroll_ad_asset_hostname=u}}this.pm.data.ad_asset_url=i==null?void 0:i.ad_asset_url,this.pm.data.ad_tag_url=i==null?void 0:i.ad_tag_url,this.pm.data.ad_creative_id=i==null?void 0:i.ad_creative_id,this.pm.data.ad_id=i==null?void 0:i.ad_id,this.pm.data.ad_universal_id=i==null?void 0:i.ad_universal_id}}]),r}(),zt=wa;var Je=J(Q());var Ea=function r(e){\"use strict\";D(this,r);var t,i,a=function(){e.disableRebufferTracking||(O(e.data,\"view_waiting_rebuffer_count\",1),t=A.now(),i=Je.default.setInterval(function(){if(t){var v=A.now();O(e.data,\"view_waiting_rebuffer_duration\",v-t),t=v}},250))},n=function(){e.disableRebufferTracking||t&&(O(e.data,\"view_waiting_rebuffer_duration\",A.now()-t),t=!1,Je.default.clearInterval(i))},o=!1,s=function(){o=!0},u=function(){o=!1,n()};e.on(\"waiting\",function(){o&&a()}),e.on(\"playing\",function(){n(),s()}),e.on(\"pause\",u),e.on(\"seeking\",u)},Kt=Ea;var ka=function r(e){\"use strict\";var t=this;D(this,r),l(this,\"lastWallClockTime\",void 0);var i=function(){t.lastWallClockTime=A.now(),e.on(\"before*\",a)},a=function(n){var o=A.now(),s=t.lastWallClockTime;t.lastWallClockTime=o,o-s>3e4&&(e.emit(\"devicesleep\",{viewer_time:s}),Object.assign(e.data,{viewer_time:s}),e.send(\"devicesleep\"),e.emit(\"devicewake\",{viewer_time:o}),Object.assign(e.data,{viewer_time:o}),e.send(\"devicewake\"))};e.one(\"playbackheartbeat\",i),e.on(\"playbackheartbeatend\",function(){e.off(\"before*\",a),e.one(\"playbackheartbeat\",i)})},Yt=ka;var Be=J(Q());var Qe=function(r){return r()}(function(){var r=function(){for(var i=0,a={};i<arguments.length;i++){var n=arguments[i];for(var o in n)a[o]=n[o]}return a};function e(t){function i(a,n,o){var s;if(typeof document!=\"undefined\"){if(arguments.length>1){if(o=r({path:\"/\"},i.defaults,o),typeof o.expires==\"number\"){var u=new Date;u.setMilliseconds(u.getMilliseconds()+o.expires*864e5),o.expires=u}try{s=JSON.stringify(n),/^[\\{\\[]/.test(s)&&(n=s)}catch(b){}return t.write?n=t.write(n,a):n=encodeURIComponent(String(n)).replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g,decodeURIComponent),a=encodeURIComponent(String(a)),a=a.replace(/%(23|24|26|2B|5E|60|7C)/g,decodeURIComponent),a=a.replace(/[\\(\\)]/g,escape),document.cookie=[a,\"=\",n,o.expires?\"; expires=\"+o.expires.toUTCString():\"\",o.path?\"; path=\"+o.path:\"\",o.domain?\"; domain=\"+o.domain:\"\",o.secure?\"; secure\":\"\"].join(\"\")}a||(s={});for(var v=document.cookie?document.cookie.split(\"; \"):[],w=/(%[0-9A-Z]{2})+/g,k=0;k<v.length;k++){var y=v[k].split(\"=\"),c=y.slice(1).join(\"=\");c.charAt(0)==='\"'&&(c=c.slice(1,-1));try{var p=y[0].replace(w,decodeURIComponent);if(c=t.read?t.read(c,p):t(c,p)||c.replace(w,decodeURIComponent),this.json)try{c=JSON.parse(c)}catch(b){}if(a===p){s=c;break}a||(s[p]=c)}catch(b){}}return s}}return i.set=i,i.get=function(a){return i.call(i,a)},i.getJSON=function(){return i.apply({json:!0},[].slice.call(arguments))},i.defaults={},i.remove=function(a,n){i(a,\"\",r(n,{expires:-1}))},i.withConverter=e,i}return e(function(){})});var Xt=\"muxData\",xa=function(r){return Object.entries(r).map(function(e){var t=H(e,2),i=t[0],a=t[1];return\"\".concat(i,\"=\").concat(a)}).join(\"&\")},Da=function(r){return r.split(\"&\").reduce(function(e,t){var i=H(t.split(\"=\"),2),a=i[0],n=i[1],o=+n,s=n&&o==n?o:n;return e[a]=s,e},{})},$t=function(){var e;try{e=Da(Qe.get(Xt)||\"\")}catch(t){e={}}return e},Zt=function(e){try{Qe.set(Xt,xa(e),{expires:365})}catch(t){}},er=function(){var e=$t();return e.mux_viewer_id=e.mux_viewer_id||ee(),e.msn=e.msn||Math.random(),Zt(e),{mux_viewer_id:e.mux_viewer_id,mux_sample_number:e.msn}},tr=function(){var e=$t(),t=A.now();return e.session_start&&(e.sst=e.session_start,delete e.session_start),e.session_id&&(e.sid=e.session_id,delete e.session_id),e.session_expires&&(e.sex=e.session_expires,delete e.session_expires),(!e.sex||e.sex<t)&&(e.sid=ee(),e.sst=t),e.sex=t+25*60*1e3,Zt(e),{session_id:e.sid,session_start:e.sst,session_expires:e.sex}};function ze(r,e){var t=e.beaconCollectionDomain,i=e.beaconDomain;if(t)return\"https://\"+t;r=r||\"inferred\";var a=i||\"litix.io\";return r.match(/^[a-z0-9]+$/)?\"https://\"+r+\".\"+a:\"https://img.litix.io/a.gif\"}var rr=J(Q()),ar=function(){var e;switch(ir()){case\"cellular\":e=\"cellular\";break;case\"ethernet\":e=\"wired\";break;case\"wifi\":e=\"wifi\";break;case void 0:break;default:e=\"other\"}return e},ir=function(){var e=rr.default.navigator,t=e&&(e.connection||e.mozConnection||e.webkitConnection);return t&&t.type};ar.getConnectionFromAPI=ir;var nr=ar;var Sa={a:\"env\",b:\"beacon\",c:\"custom\",d:\"ad\",e:\"event\",f:\"experiment\",i:\"internal\",m:\"mux\",n:\"response\",p:\"player\",q:\"request\",r:\"retry\",s:\"session\",t:\"timestamp\",u:\"viewer\",v:\"video\",w:\"page\",x:\"view\",y:\"sub\"},Ra=sr(Sa),qa={ad:\"ad\",ag:\"aggregate\",ap:\"api\",al:\"application\",ar:\"architecture\",as:\"asset\",au:\"autoplay\",av:\"average\",bi:\"bitrate\",br:\"break\",bw:\"browser\",by:\"bytes\",bz:\"business\",ca:\"cached\",cb:\"cancel\",cc:\"codec\",cd:\"code\",cg:\"category\",ch:\"changed\",ck:\"clicked\",cl:\"canceled\",cn:\"config\",co:\"count\",ce:\"counter\",cp:\"complete\",cr:\"creative\",ct:\"content\",cu:\"current\",cx:\"connection\",cz:\"context\",dg:\"downscaling\",dm:\"domain\",dn:\"cdn\",do:\"downscale\",dr:\"drm\",dp:\"dropped\",du:\"duration\",dv:\"device\",ec:\"encoding\",ed:\"edge\",en:\"end\",eg:\"engine\",em:\"embed\",er:\"error\",ep:\"experiments\",es:\"errorcode\",et:\"errortext\",ee:\"event\",ev:\"events\",ex:\"expires\",ez:\"exception\",fa:\"failed\",fi:\"first\",fm:\"family\",ft:\"format\",fp:\"fps\",fq:\"frequency\",fr:\"frame\",fs:\"fullscreen\",ha:\"has\",hb:\"holdback\",he:\"headers\",ho:\"host\",hn:\"hostname\",ht:\"height\",id:\"id\",ii:\"init\",in:\"instance\",ip:\"ip\",is:\"is\",ke:\"key\",la:\"language\",lb:\"labeled\",le:\"level\",li:\"live\",ld:\"loaded\",lo:\"load\",ls:\"lists\",lt:\"latency\",ma:\"max\",md:\"media\",me:\"message\",mf:\"manifest\",mi:\"mime\",ml:\"midroll\",mm:\"min\",mn:\"manufacturer\",mo:\"model\",mx:\"mux\",ne:\"newest\",nm:\"name\",no:\"number\",on:\"on\",os:\"os\",pa:\"paused\",pb:\"playback\",pd:\"producer\",pe:\"percentage\",pf:\"played\",pg:\"program\",ph:\"playhead\",pi:\"plugin\",pl:\"preroll\",pn:\"playing\",po:\"poster\",pr:\"preload\",ps:\"position\",pt:\"part\",py:\"property\",ra:\"rate\",rd:\"requested\",re:\"rebuffer\",rf:\"rendition\",rm:\"remote\",ro:\"ratio\",rp:\"response\",rq:\"request\",rs:\"requests\",sa:\"sample\",sd:\"skipped\",se:\"session\",sk:\"seek\",sm:\"stream\",so:\"source\",sq:\"sequence\",sr:\"series\",st:\"start\",su:\"startup\",sv:\"server\",sw:\"software\",sy:\"severity\",ta:\"tag\",tc:\"tech\",te:\"text\",tg:\"target\",th:\"throughput\",ti:\"time\",tl:\"total\",to:\"to\",tt:\"title\",ty:\"type\",ug:\"upscaling\",un:\"universal\",up:\"upscale\",ur:\"url\",us:\"user\",va:\"variant\",vd:\"viewed\",vi:\"video\",ve:\"version\",vw:\"view\",vr:\"viewer\",wd:\"width\",wa:\"watch\",wt:\"waiting\"},or=sr(qa);function sr(r){var e={};for(var t in r)r.hasOwnProperty(t)&&(e[r[t]]=t);return e}function ve(r){var e={},t={};return Object.keys(r).forEach(function(i){var a=!1;if(r.hasOwnProperty(i)&&r[i]!==void 0){var n=i.split(\"_\"),o=n[0],s=Ra[o];s||(q.info(\"Data key word `\"+n[0]+\"` not expected in \"+i),s=o+\"_\"),n.splice(1).forEach(function(u){u===\"url\"&&(a=!0),or[u]?s+=or[u]:Number(u)&&Math.floor(Number(u))===Number(u)?s+=u:(q.info(\"Data key word `\"+u+\"` not expected in \"+i),s+=\"_\"+u+\"_\")}),a?t[s]=r[i]:e[s]=r[i]}}),Object.assign(e,t)}var ae=J(Q());var Aa={maxBeaconSize:300,maxQueueLength:3600,baseTimeBetweenBeacons:1e4,maxPayloadKBSize:500},Oa=56*1024,Ia=[\"hb\",\"requestcompleted\",\"requestfailed\",\"requestcanceled\"],Pa=\"https://img.litix.io\",$=function(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};this._beaconUrl=e||Pa,this._eventQueue=[],this._postInFlight=!1,this._failureCount=0,this._sendTimeout=!1,this._options=Object.assign({},Aa,t)};$.prototype.queueEvent=function(r,e){var t=Object.assign({},e);return this._eventQueue.length<=this._options.maxQueueLength||r===\"eventrateexceeded\"?(this._eventQueue.push(t),this._sendTimeout||this._startBeaconSending(),this._eventQueue.length<=this._options.maxQueueLength):!1};$.prototype.flushEvents=function(){var r=arguments.length>0&&arguments[0]!==void 0?arguments[0]:!1;if(r&&this._eventQueue.length===1){this._eventQueue.pop();return}this._eventQueue.length&&this._sendBeaconQueue(),this._startBeaconSending()};$.prototype.destroy=function(){var r=arguments.length>0&&arguments[0]!==void 0?arguments[0]:!1;this.destroyed=!0,r?this._clearBeaconQueue():this.flushEvents(),ae.default.clearTimeout(this._sendTimeout)};$.prototype._clearBeaconQueue=function(){var r=this._eventQueue.length>this._options.maxBeaconSize?this._eventQueue.length-this._options.maxBeaconSize:0,e=this._eventQueue.slice(r);r>0&&Object.assign(e[e.length-1],ve({mux_view_message:\"event queue truncated\"}));var t=this._createPayload(e);ur(this._beaconUrl,t,!0,function(){})};$.prototype._sendBeaconQueue=function(){var r=this;if(!this._postInFlight){var e=this._eventQueue.slice(0,this._options.maxBeaconSize);this._eventQueue=this._eventQueue.slice(this._options.maxBeaconSize),this._postInFlight=!0;var t=this._createPayload(e),i=A.now();ur(this._beaconUrl,t,!1,function(a,n){n?(r._eventQueue=e.concat(r._eventQueue),r._failureCount+=1,q.info(\"Error sending beacon: \"+n)):r._failureCount=0,r._roundTripTime=A.now()-i,r._postInFlight=!1})}};$.prototype._getNextBeaconTime=function(){if(!this._failureCount)return this._options.baseTimeBetweenBeacons;var r=Math.pow(2,this._failureCount-1);return r=r*Math.random(),(1+r)*this._options.baseTimeBetweenBeacons};$.prototype._startBeaconSending=function(){var r=this;ae.default.clearTimeout(this._sendTimeout),!this.destroyed&&(this._sendTimeout=ae.default.setTimeout(function(){r._eventQueue.length&&r._sendBeaconQueue(),r._startBeaconSending()},this._getNextBeaconTime()))};$.prototype._createPayload=function(r){var e=this,t={transmission_timestamp:Math.round(A.now())};this._roundTripTime&&(t.rtt_ms=Math.round(this._roundTripTime));var i,a,n,o=function(){i=JSON.stringify({metadata:t,events:a||r}),n=i.length/1024},s=function(){return n<=e._options.maxPayloadKBSize};return o(),s()||(q.info(\"Payload size is too big (\"+n+\" kb). Removing unnecessary events.\"),a=r.filter(function(u){return Ia.indexOf(u.e)===-1}),o()),s()||(q.info(\"Payload size still too big (\"+n+\" kb). Cropping fields..\"),a.forEach(function(u){for(var v in u){var w=u[v],k=50*1024;typeof w==\"string\"&&w.length>k&&(u[v]=w.substring(0,k))}}),o()),i};var Na=function(r){return r.length<=Oa},ur=function(r,e,t,i){if(t&&navigator&&navigator.sendBeacon&&navigator.sendBeacon(r,e)){i();return}if(ae.default.fetch){ae.default.fetch(r,{method:\"POST\",body:e,headers:{\"Content-Type\":\"text/plain\"},keepalive:Na(e)}).then(function(n){return i(null,n.ok?null:\"Error\")}).catch(function(n){return i(null,n)});return}if(ae.default.XMLHttpRequest){var a=new ae.default.XMLHttpRequest;a.onreadystatechange=function(){if(a.readyState===4)return i(null,a.status!==200?\"error\":void 0)},a.open(\"POST\",r),a.setRequestHeader(\"Content-Type\",\"text/plain\"),a.send(e);return}i()},dr=$;var La=[\"env_key\",\"view_id\",\"view_sequence_number\",\"player_sequence_number\",\"beacon_domain\",\"player_playhead_time\",\"viewer_time\",\"mux_api_version\",\"event\",\"video_id\",\"player_instance_id\",\"player_error_code\",\"player_error_message\",\"player_error_context\",\"player_error_severity\",\"player_error_business_exception\"],Ca=[\"adplay\",\"adplaying\",\"adpause\",\"adfirstquartile\",\"admidpoint\",\"adthirdquartile\",\"adended\",\"adresponse\",\"adrequest\"],Ma=[\"ad_id\",\"ad_creative_id\",\"ad_universal_id\"],Ha=[\"viewstart\",\"error\",\"ended\",\"viewend\"],Ba=10*60*1e3,lr=function(){\"use strict\";function r(e,t){var i=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};D(this,r);var a,n,o,s,u,v,w,k,y,c,p,b;l(this,\"mux\",void 0),l(this,\"envKey\",void 0),l(this,\"options\",void 0),l(this,\"eventQueue\",void 0),l(this,\"sampleRate\",void 0),l(this,\"disableCookies\",void 0),l(this,\"respectDoNotTrack\",void 0),l(this,\"previousBeaconData\",void 0),l(this,\"lastEventTime\",void 0),l(this,\"rateLimited\",void 0),l(this,\"pageLevelData\",void 0),l(this,\"viewerData\",void 0),this.mux=e,this.envKey=t,this.options=i,this.previousBeaconData=null,this.lastEventTime=0,this.rateLimited=!1,this.eventQueue=new dr(ze(this.envKey,this.options));var x;this.sampleRate=(x=this.options.sampleRate)!==null&&x!==void 0?x:1;var m;this.disableCookies=(m=this.options.disableCookies)!==null&&m!==void 0?m:!1;var f;this.respectDoNotTrack=(f=this.options.respectDoNotTrack)!==null&&f!==void 0?f:!1,this.previousBeaconData=null,this.lastEventTime=0,this.rateLimited=!1,this.pageLevelData={mux_api_version:this.mux.API_VERSION,mux_embed:this.mux.NAME,mux_embed_version:this.mux.VERSION,viewer_application_name:(a=this.options.platform)===null||a===void 0?void 0:a.name,viewer_application_version:(n=this.options.platform)===null||n===void 0?void 0:n.version,viewer_application_engine:(o=this.options.platform)===null||o===void 0?void 0:o.layout,viewer_device_name:(s=this.options.platform)===null||s===void 0?void 0:s.product,viewer_device_category:\"\",viewer_device_manufacturer:(u=this.options.platform)===null||u===void 0?void 0:u.manufacturer,viewer_os_family:(w=this.options.platform)===null||w===void 0||(v=w.os)===null||v===void 0?void 0:v.family,viewer_os_architecture:(y=this.options.platform)===null||y===void 0||(k=y.os)===null||k===void 0?void 0:k.architecture,viewer_os_version:(p=this.options.platform)===null||p===void 0||(c=p.os)===null||c===void 0?void 0:c.version,viewer_connection_type:nr(),page_url:Be.default===null||Be.default===void 0||(b=Be.default.location)===null||b===void 0?void 0:b.href},this.viewerData=this.disableCookies?{}:er()}return L(r,[{key:\"send\",value:function(t,i){if(!(!t||!(i!=null&&i.view_id))){if(this.respectDoNotTrack&&ce())return q.info(\"Not sending `\"+t+\"` because Do Not Track is enabled\");if(!i||typeof i!=\"object\")return q.error(\"A data object was expected in send() but was not provided\");var a=this.disableCookies?{}:tr(),n=fe(ue({},this.pageLevelData,i,a,this.viewerData),{event:t,env_key:this.envKey});n.user_id&&(n.viewer_user_id=n.user_id,delete n.user_id);var o,s=((o=n.mux_sample_number)!==null&&o!==void 0?o:0)>=this.sampleRate,u=this._deduplicateBeaconData(t,n),v=ve(u);if(this.lastEventTime=this.mux.utils.now(),s)return q.info(\"Not sending event due to sample rate restriction\",t,n,v);if(this.envKey||q.info(\"Missing environment key (envKey) - beacons will be dropped if the video source is not a valid mux video URL\",t,n,v),!this.rateLimited){if(q.info(\"Sending event\",t,n,v),this.rateLimited=!this.eventQueue.queueEvent(t,v),this.mux.WINDOW_UNLOADING&&t===\"viewend\")this.eventQueue.destroy(!0);else if(this.mux.WINDOW_HIDDEN&&t===\"hb\"?this.eventQueue.flushEvents(!0):Ha.indexOf(t)>=0&&this.eventQueue.flushEvents(),this.rateLimited)return n.event=\"eventrateexceeded\",v=ve(n),this.eventQueue.queueEvent(n.event,v),q.error(\"Beaconing disabled due to rate limit.\")}}}},{key:\"destroy\",value:function(){this.eventQueue.destroy(!1)}},{key:\"_deduplicateBeaconData\",value:function(t,i){var a=this,n={},o=i.view_id;if(o===\"-1\"||t===\"viewstart\"||t===\"viewend\"||!this.previousBeaconData||this.mux.utils.now()-this.lastEventTime>=Ba)n=ue({},i),o&&(this.previousBeaconData=n),o&&t===\"viewend\"&&(this.previousBeaconData=null);else{var s=t.indexOf(\"request\")===0;Object.entries(i).forEach(function(u){var v=H(u,2),w=v[0],k=v[1];a.previousBeaconData&&(k!==a.previousBeaconData[w]||La.indexOf(w)>-1||a.objectHasChanged(s,w,k,a.previousBeaconData[w])||a.eventRequiresKey(t,w))&&(n[w]=k,a.previousBeaconData[w]=k)})}return n}},{key:\"objectHasChanged\",value:function(t,i,a,n){return!t||i.indexOf(\"request_\")!==0?!1:i===\"request_response_headers\"||typeof a!=\"object\"||typeof n!=\"object\"?!0:Object.keys(a||{}).length!==Object.keys(n||{}).length}},{key:\"eventRequiresKey\",value:function(t,i){return!!(t===\"renditionchange\"&&i.indexOf(\"video_source_\")===0||Ma.includes(i)&&Ca.includes(t))}}]),r}();var Ua=function r(e){\"use strict\";D(this,r);var t=0,i=0,a=0,n=0,o=0,s=0,u=0,v=function(y,c){var p=c.request_start,b=c.request_response_start,x=c.request_response_end,m=c.request_bytes_loaded;n++;var f,_;if(b?(f=b-(p!=null?p:0),_=(x!=null?x:0)-b):_=(x!=null?x:0)-(p!=null?p:0),_>0&&m&&m>0){var d=m/_*8e3;o++,i+=m,a+=_,e.data.view_min_request_throughput=Math.min(e.data.view_min_request_throughput||1/0,d),e.data.view_average_request_throughput=i/a*8e3,e.data.view_request_count=n,f>0&&(t+=f,e.data.view_max_request_latency=Math.max(e.data.view_max_request_latency||0,f),e.data.view_average_request_latency=t/o)}},w=function(y,c){n++,s++,e.data.view_request_count=n,e.data.view_request_failed_count=s},k=function(y,c){n++,u++,e.data.view_request_count=n,e.data.view_request_canceled_count=u};e.on(\"requestcompleted\",v),e.on(\"requestfailed\",w),e.on(\"requestcanceled\",k)},cr=Ua;var Fa=60*60*1e3,Va=function r(e){\"use strict\";var t=this;D(this,r),l(this,\"_lastEventTime\",void 0),e.on(\"before*\",function(i,a){var n=a.viewer_time,o=A.now(),s=t._lastEventTime;if(t._lastEventTime=o,s&&o-s>Fa){var u=Object.keys(e.data).reduce(function(w,k){return k.indexOf(\"video_\")===0?Object.assign(w,l({},k,e.data[k])):w},{});e.mux.log.info(\"Received event after at least an hour inactivity, creating a new view\");var v=e.playbackHeartbeat._playheadShouldBeProgressing;e._resetView(Object.assign({viewer_time:n},u)),e.playbackHeartbeat._playheadShouldBeProgressing=v,e.playbackHeartbeat._playheadShouldBeProgressing&&i.type!==\"play\"&&i.type!==\"adbreakstart\"&&(e.emit(\"play\",{viewer_time:n}),i.type!==\"playing\"&&e.emit(\"playing\",{viewer_time:n}))}})},_r=Va;var Wa=[\"viewstart\",\"ended\",\"loadstart\",\"pause\",\"play\",\"playing\",\"ratechange\",\"waiting\",\"adplay\",\"adpause\",\"adended\",\"aderror\",\"adplaying\",\"adrequest\",\"adresponse\",\"adbreakstart\",\"adbreakend\",\"adfirstquartile\",\"admidpoint\",\"adthirdquartile\",\"rebufferstart\",\"rebufferend\",\"seeked\",\"error\",\"hb\",\"requestcompleted\",\"requestfailed\",\"requestcanceled\",\"renditionchange\"],ja=new Set([\"requestcompleted\",\"requestfailed\",\"requestcanceled\"]),Ga=function(r){\"use strict\";kt(t,r);var e=St(t);function t(i,a,n){D(this,t);var o;o=e.call(this),l(g(o),\"DOM_CONTENT_LOADED_EVENT_END\",void 0),l(g(o),\"NAVIGATION_START\",void 0),l(g(o),\"_destroyed\",void 0),l(g(o),\"_heartBeatTimeout\",void 0),l(g(o),\"adTracker\",void 0),l(g(o),\"dashjs\",void 0),l(g(o),\"data\",void 0),l(g(o),\"disablePlayheadRebufferTracking\",void 0),l(g(o),\"disableRebufferTracking\",void 0),l(g(o),\"errorTracker\",void 0),l(g(o),\"errorTranslator\",void 0),l(g(o),\"emitTranslator\",void 0),l(g(o),\"getAdData\",void 0),l(g(o),\"getPlayheadTime\",void 0),l(g(o),\"getStateData\",void 0),l(g(o),\"stateDataTranslator\",void 0),l(g(o),\"hlsjs\",void 0),l(g(o),\"id\",void 0),l(g(o),\"longResumeTracker\",void 0),l(g(o),\"minimumRebufferDuration\",void 0),l(g(o),\"mux\",void 0),l(g(o),\"playbackEventDispatcher\",void 0),l(g(o),\"playbackHeartbeat\",void 0),l(g(o),\"playbackHeartbeatTime\",void 0),l(g(o),\"playheadTime\",void 0),l(g(o),\"seekingTracker\",void 0),l(g(o),\"sustainedRebufferThreshold\",void 0),l(g(o),\"watchTimeTracker\",void 0),l(g(o),\"currentFragmentPDT\",void 0),l(g(o),\"currentFragmentStart\",void 0),o.DOM_CONTENT_LOADED_EVENT_END=_e.domContentLoadedEventEnd(),o.NAVIGATION_START=_e.navigationStart();var s={debug:!1,minimumRebufferDuration:250,sustainedRebufferThreshold:1e3,playbackHeartbeatTime:25,beaconDomain:\"litix.io\",sampleRate:1,disableCookies:!1,respectDoNotTrack:!1,disableRebufferTracking:!1,disablePlayheadRebufferTracking:!1,errorTranslator:function(y){return y},emitTranslator:function(){for(var y=arguments.length,c=new Array(y),p=0;p<y;p++)c[p]=arguments[p];return c},stateDataTranslator:function(y){return y}};o.mux=i,o.id=a,n!=null&&n.beaconDomain&&o.mux.log.warn(\"The `beaconDomain` setting has been deprecated in favor of `beaconCollectionDomain`. Please change your integration to use `beaconCollectionDomain` instead of `beaconDomain`.\"),n=Object.assign(s,n),n.data=n.data||{},n.data.property_key&&(n.data.env_key=n.data.property_key,delete n.data.property_key),q.level=n.debug?Y.DEBUG:Y.WARN,o.getPlayheadTime=n.getPlayheadTime,o.getStateData=n.getStateData||function(){return{}},o.getAdData=n.getAdData||function(){},o.minimumRebufferDuration=n.minimumRebufferDuration,o.sustainedRebufferThreshold=n.sustainedRebufferThreshold,o.playbackHeartbeatTime=n.playbackHeartbeatTime,o.disableRebufferTracking=n.disableRebufferTracking,o.disableRebufferTracking&&o.mux.log.warn(\"Disabling rebuffer tracking. This should only be used in specific circumstances as a last resort when your player is known to unreliably track rebuffering.\"),o.disablePlayheadRebufferTracking=n.disablePlayheadRebufferTracking,o.errorTranslator=n.errorTranslator,o.emitTranslator=n.emitTranslator,o.stateDataTranslator=n.stateDataTranslator,o.playbackEventDispatcher=new lr(i,n.data.env_key,n),o.data={player_instance_id:ee(),mux_sample_rate:n.sampleRate,beacon_domain:n.beaconCollectionDomain||n.beaconDomain},o.data.view_sequence_number=1,o.data.player_sequence_number=1;var u=function(){typeof this.data.view_start==\"undefined\"&&(this.data.view_start=this.mux.utils.now(),this.emit(\"viewstart\"))}.bind(g(o));if(o.on(\"viewinit\",function(y,c){this._resetVideoData(),this._resetViewData(),this._resetErrorData(),this._updateStateData(),Object.assign(this.data,c),this._initializeViewData(),this.one(\"play\",u),this.one(\"adbreakstart\",u)}),o.on(\"videochange\",function(y,c){this._resetView(c)}),o.on(\"programchange\",function(y,c){this.data.player_is_paused&&this.mux.log.warn(\"The `programchange` event is intended to be used when the content changes mid playback without the video source changing, however the video is not currently playing. If the video source is changing please use the videochange event otherwise you will lose startup time information.\"),this._resetView(Object.assign(c,{view_program_changed:!0})),u(),this.emit(\"play\"),this.emit(\"playing\")}),o.on(\"fragmentchange\",function(y,c){this.currentFragmentPDT=c.currentFragmentPDT,this.currentFragmentStart=c.currentFragmentStart}),o.on(\"destroy\",o.destroy),typeof window!=\"undefined\"&&typeof window.addEventListener==\"function\"&&typeof window.removeEventListener==\"function\"){var v=function(){var y=typeof o.data.view_start!=\"undefined\";o.mux.WINDOW_HIDDEN=document.visibilityState===\"hidden\",y&&o.mux.WINDOW_HIDDEN&&(o.data.player_is_paused||o.emit(\"hb\"))};window.addEventListener(\"visibilitychange\",v,!1);var w=function(y){y.persisted||o.destroy()};window.addEventListener(\"pagehide\",w,!1),o.on(\"destroy\",function(){window.removeEventListener(\"visibilitychange\",v),window.removeEventListener(\"pagehide\",w)})}o.on(\"playerready\",function(y,c){Object.assign(this.data,c)}),Wa.forEach(function(y){o.on(y,function(c,p){y.indexOf(\"ad\")!==0&&this._updateStateData(),Object.assign(this.data,p),this._sanitizeData()}),o.on(\"after\"+y,function(){(y!==\"error\"||this.errorTracker.viewErrored)&&this.send(y)})}),o.on(\"viewend\",function(y,c){Object.assign(o.data,c)});var k=function(c){var p=this.mux.utils.now();this.data.player_init_time&&(this.data.player_startup_time=p-this.data.player_init_time),!this.mux.PLAYER_TRACKED&&this.NAVIGATION_START&&(this.mux.PLAYER_TRACKED=!0,(this.data.player_init_time||this.DOM_CONTENT_LOADED_EVENT_END)&&(this.data.page_load_time=Math.min(this.data.player_init_time||1/0,this.DOM_CONTENT_LOADED_EVENT_END||1/0)-this.NAVIGATION_START)),this.send(\"playerready\"),delete this.data.player_startup_time,delete this.data.page_load_time};return o.one(\"playerready\",k),o.longResumeTracker=new _r(g(o)),o.errorTracker=new Mt(g(o)),new Yt(g(o)),o.seekingTracker=new Jt(g(o)),o.playheadTime=new Ut(g(o)),o.playbackHeartbeat=new Ct(g(o)),new Gt(g(o)),o.watchTimeTracker=new Ht(g(o)),new Bt(g(o)),o.adTracker=new zt(g(o)),new Wt(g(o)),new Vt(g(o)),new jt(g(o)),new Kt(g(o)),new cr(g(o)),n.hlsjs&&o.addHLSJS(n),n.dashjs&&o.addDashJS(n),o.emit(\"viewinit\",n.data),o}return L(t,[{key:\"emit\",value:function(a,n){var o,s=Object.assign({viewer_time:this.mux.utils.now()},n),u=[a,s];if(this.emitTranslator)try{u=this.emitTranslator(a,s)}catch(v){this.mux.log.warn(\"Exception in emit translator callback.\",v)}u!=null&&u.length&&(o=De(X(t.prototype),\"emit\",this)).call.apply(o,[this].concat(V(u)))}},{key:\"destroy\",value:function(){this._destroyed||(this._destroyed=!0,typeof this.data.view_start!=\"undefined\"&&(this.emit(\"viewend\"),this.send(\"viewend\")),this.playbackEventDispatcher.destroy(),this.removeHLSJS(),this.removeDashJS(),window.clearTimeout(this._heartBeatTimeout))}},{key:\"send\",value:function(a){if(this.data.view_id){var n=Object.assign({},this.data),o=[\"player_program_time\",\"player_manifest_newest_program_time\",\"player_live_edge_program_time\",\"player_program_time\",\"video_holdback\",\"video_part_holdback\",\"video_target_duration\",\"video_part_target_duration\"];if(n.video_source_is_live===void 0&&(n.player_source_duration===1/0||n.video_source_duration===1/0?n.video_source_is_live=!0:(n.player_source_duration>0||n.video_source_duration>0)&&(n.video_source_is_live=!1)),n.video_source_is_live||o.forEach(function(w){n[w]=void 0}),n.video_source_url=n.video_source_url||n.player_source_url,n.video_source_url){var s=H(re(n.video_source_url),2),u=s[0],v=s[1];n.video_source_domain=v,n.video_source_hostname=u}delete n.ad_request_id,this.playbackEventDispatcher.send(a,n),this.data.view_sequence_number++,this.data.player_sequence_number++,ja.has(a)||this._restartHeartBeat(),a===\"viewend\"&&delete this.data.view_id}}},{key:\"_resetView\",value:function(a){this.emit(\"viewend\"),this.send(\"viewend\"),this.emit(\"viewinit\",a)}},{key:\"_updateStateData\",value:function(){var a=this.getStateData();if(typeof this.stateDataTranslator==\"function\")try{a=this.stateDataTranslator(a)}catch(n){this.mux.log.warn(\"Exception in stateDataTranslator translator callback.\",n)}Object.assign(this.data,a),this.playheadTime._updatePlayheadTime(),this._sanitizeData()}},{key:\"_sanitizeData\",value:function(){var a=this,n=[\"player_width\",\"player_height\",\"video_source_width\",\"video_source_height\",\"player_playhead_time\",\"video_source_bitrate\"];n.forEach(function(s){var u=parseInt(a.data[s],10);a.data[s]=isNaN(u)?void 0:u});var o=[\"player_source_url\",\"video_source_url\"];o.forEach(function(s){if(a.data[s]){var u=a.data[s].toLowerCase();(u.indexOf(\"data:\")===0||u.indexOf(\"blob:\")===0)&&(a.data[s]=\"MSE style URL\")}})}},{key:\"_resetVideoData\",value:function(){var a=this;Object.keys(this.data).forEach(function(n){n.indexOf(\"video_\")===0&&delete a.data[n]})}},{key:\"_resetViewData\",value:function(){var a=this;Object.keys(this.data).forEach(function(n){n.indexOf(\"view_\")===0&&delete a.data[n]}),this.data.view_sequence_number=1}},{key:\"_resetErrorData\",value:function(){delete this.data.player_error_code,delete this.data.player_error_message,delete this.data.player_error_context,delete this.data.player_error_severity,delete this.data.player_error_business_exception}},{key:\"_initializeViewData\",value:function(){var a=this,n=this.data.view_id=ee(),o=function(){n===a.data.view_id&&O(a.data,\"player_view_count\",1)};this.data.player_is_paused?this.one(\"play\",o):o()}},{key:\"_restartHeartBeat\",value:function(){var a=this;window.clearTimeout(this._heartBeatTimeout),this._heartBeatTimeout=window.setTimeout(function(){a.data.player_is_paused||a.emit(\"hb\")},1e4)}},{key:\"addHLSJS\",value:function(a){if(!a.hlsjs){this.mux.log.warn(\"You must pass a valid hlsjs instance in order to track it.\");return}if(this.hlsjs){this.mux.log.warn(\"An instance of HLS.js is already being monitored for this player.\");return}this.hlsjs=a.hlsjs,qt(this.mux,this.id,a.hlsjs,{},a.Hls||window.Hls)}},{key:\"removeHLSJS\",value:function(){this.hlsjs&&(At(this.hlsjs),this.hlsjs=void 0)}},{key:\"addDashJS\",value:function(a){if(!a.dashjs){this.mux.log.warn(\"You must pass a valid dashjs instance in order to track it.\");return}if(this.dashjs){this.mux.log.warn(\"An instance of Dash.js is already being monitored for this player.\");return}this.dashjs=a.dashjs,It(this.mux,this.id,a.dashjs)}},{key:\"removeDashJS\",value:function(){this.dashjs&&(Pt(this.dashjs),this.dashjs=void 0)}}]),t}(Lt),fr=Ga;var he=J(Br());function it(){return he.default&&!!(he.default.fullscreenElement||he.default.webkitFullscreenElement||he.default.mozFullScreenElement||he.default.msFullscreenElement)}var hi=[\"loadstart\",\"pause\",\"play\",\"playing\",\"seeking\",\"seeked\",\"timeupdate\",\"ratechange\",\"stalled\",\"waiting\",\"error\",\"ended\"],yi={1:\"MEDIA_ERR_ABORTED\",2:\"MEDIA_ERR_NETWORK\",3:\"MEDIA_ERR_DECODE\",4:\"MEDIA_ERR_SRC_NOT_SUPPORTED\"};function nt(r,e,t){var i=H(se(e),3),a=i[0],n=i[1],o=i[2],s=r.log,u=r.utils.getComputedStyle,v=r.utils.secondsToMs,w={automaticErrorTracking:!0};if(a){if(o!==\"video\"&&o!==\"audio\")return s.error(\"The element of `\"+n+\"` was not a media element.\")}else return s.error(\"No element was found with the `\"+n+\"` query selector.\");a.mux&&(a.mux.destroy(),delete a.mux,s.warn(\"Already monitoring this video element, replacing existing event listeners\"));var k={getPlayheadTime:function(){return v(a.currentTime)},getStateData:function(){var p,b,x,m=((p=(b=this).getPlayheadTime)===null||p===void 0?void 0:p.call(b))||v(a.currentTime),f=this.hlsjs&&this.hlsjs.url,_=this.dashjs&&typeof this.dashjs.getSource==\"function\"&&this.dashjs.getSource(),d={player_is_paused:a.paused,player_width:parseInt(u(a,\"width\")),player_height:parseInt(u(a,\"height\")),player_autoplay_on:a.autoplay,player_preload_on:a.preload,player_language_code:a.lang,player_is_fullscreen:it(),video_poster_url:a.poster,video_source_url:f||_||a.currentSrc,video_source_duration:v(a.duration),video_source_height:a.videoHeight,video_source_width:a.videoWidth,view_dropped_frame_count:a==null||(x=a.getVideoPlaybackQuality)===null||x===void 0?void 0:x.call(a).droppedVideoFrames};if(a.getStartDate&&m>0){var h=a.getStartDate();if(h&&typeof h.getTime==\"function\"&&h.getTime()){var T=h.getTime();if(d.player_program_time=T+m,a.seekable.length>0){var E=T+a.seekable.end(a.seekable.length-1);d.player_live_edge_program_time=E}}}return d}};t=Object.assign(w,t,k),t.data=Object.assign({player_software:\"HTML5 Video Element\",player_mux_plugin_name:\"VideoElementMonitor\",player_mux_plugin_version:r.VERSION},t.data),a.mux=a.mux||{},a.mux.deleted=!1,a.mux.emit=function(c,p){r.emit(n,c,p)},a.mux.updateData=function(c){a.mux.emit(\"hb\",c)};var y=function(){s.error(\"The monitor for this video element has already been destroyed.\")};a.mux.destroy=function(){Object.keys(a.mux.listeners).forEach(function(c){a.removeEventListener(c,a.mux.listeners[c],!1)}),delete a.mux.listeners,a.mux.destroy=y,a.mux.swapElement=y,a.mux.emit=y,a.mux.addHLSJS=y,a.mux.addDashJS=y,a.mux.removeHLSJS=y,a.mux.removeDashJS=y,a.mux.updateData=y,a.mux.setEmitTranslator=y,a.mux.setStateDataTranslator=y,a.mux.setGetPlayheadTime=y,a.mux.deleted=!0,r.emit(n,\"destroy\")},a.mux.swapElement=function(c){var p=H(se(c),3),b=p[0],x=p[1],m=p[2];if(b){if(m!==\"video\"&&m!==\"audio\")return r.log.error(\"The element of `\"+x+\"` was not a media element.\")}else return r.log.error(\"No element was found with the `\"+x+\"` query selector.\");b.muxId=a.muxId,delete a.muxId,b.mux=b.mux||{},b.mux.listeners=Object.assign({},a.mux.listeners),delete a.mux.listeners,Object.keys(b.mux.listeners).forEach(function(f){a.removeEventListener(f,b.mux.listeners[f],!1),b.addEventListener(f,b.mux.listeners[f],!1)}),b.mux.swapElement=a.mux.swapElement,b.mux.destroy=a.mux.destroy,delete a.mux,a=b},a.mux.addHLSJS=function(c){r.addHLSJS(n,c)},a.mux.addDashJS=function(c){r.addDashJS(n,c)},a.mux.removeHLSJS=function(){r.removeHLSJS(n)},a.mux.removeDashJS=function(){r.removeDashJS(n)},a.mux.setEmitTranslator=function(c){r.setEmitTranslator(n,c)},a.mux.setStateDataTranslator=function(c){r.setStateDataTranslator(n,c)},a.mux.setGetPlayheadTime=function(c){c||(c=t.getPlayheadTime),r.setGetPlayheadTime(n,c)},r.init(n,t),r.emit(n,\"playerready\"),a.paused||(r.emit(n,\"play\"),a.readyState>2&&r.emit(n,\"playing\")),a.mux.listeners={},hi.forEach(function(c){c===\"error\"&&!t.automaticErrorTracking||(a.mux.listeners[c]=function(){var p={};if(c===\"error\"){if(!a.error||a.error.code===1)return;p.player_error_code=a.error.code,p.player_error_message=yi[a.error.code]||a.error.message}r.emit(n,c,p)},a.addEventListener(c,a.mux.listeners[c],!1))})}function ot(r,e,t,i){var a=i;if(r&&typeof r[e]==\"function\")try{a=r[e].apply(r,t)}catch(n){q.info(\"safeCall error\",n)}return a}var ge=J(Q()),ye;ge.default&&ge.default.WeakMap&&(ye=new WeakMap);function st(r,e){if(!r||!e||!ge.default||typeof ge.default.getComputedStyle!=\"function\")return\"\";var t;return ye&&ye.has(r)&&(t=ye.get(r)),t||(t=ge.default.getComputedStyle(r,null),ye&&ye.set(r,t)),t.getPropertyValue(e)}function ut(r){return Math.floor(r*1e3)}var le={TARGET_DURATION:\"#EXT-X-TARGETDURATION\",PART_INF:\"#EXT-X-PART-INF\",SERVER_CONTROL:\"#EXT-X-SERVER-CONTROL\",INF:\"#EXTINF\",PROGRAM_DATE_TIME:\"#EXT-X-PROGRAM-DATE-TIME\",VERSION:\"#EXT-X-VERSION\",SESSION_DATA:\"#EXT-X-SESSION-DATA\"},Fe=function(e){return this.buffer=\"\",this.manifest={segments:[],serverControl:{},sessionData:{}},this.currentUri={},this.process(e),this.manifest};Fe.prototype.process=function(r){var e;for(this.buffer+=r,e=this.buffer.indexOf(\"\\n\");e>-1;e=this.buffer.indexOf(\"\\n\"))this.processLine(this.buffer.substring(0,e)),this.buffer=this.buffer.substring(e+1)};Fe.prototype.processLine=function(r){var e=r.indexOf(\":\"),t=wi(r,e),i=t[0],a=t.length===2?lt(t[1]):void 0;if(i[0]!==\"#\")this.currentUri.uri=i,this.manifest.segments.push(this.currentUri),this.manifest.targetDuration&&!(\"duration\"in this.currentUri)&&(this.currentUri.duration=this.manifest.targetDuration),this.currentUri={};else switch(i){case le.TARGET_DURATION:{if(!isFinite(a)||a<0)return;this.manifest.targetDuration=a,this.setHoldBack();break}case le.PART_INF:{dt(this.manifest,t),this.manifest.partInf.partTarget&&(this.manifest.partTargetDuration=this.manifest.partInf.partTarget),this.setHoldBack();break}case le.SERVER_CONTROL:{dt(this.manifest,t),this.setHoldBack();break}case le.INF:{a===0?this.currentUri.duration=.01:a>0&&(this.currentUri.duration=a);break}case le.PROGRAM_DATE_TIME:{var n=a,o=new Date(n);this.manifest.dateTimeString||(this.manifest.dateTimeString=n,this.manifest.dateTimeObject=o),this.currentUri.dateTimeString=n,this.currentUri.dateTimeObject=o;break}case le.VERSION:{dt(this.manifest,t);break}case le.SESSION_DATA:{var s=Ei(t[1]),u=Ce(s);Object.assign(this.manifest.sessionData,u)}}};Fe.prototype.setHoldBack=function(){var r=this.manifest,e=r.serverControl,t=r.targetDuration,i=r.partTargetDuration;if(e){var a=\"holdBack\",n=\"partHoldBack\",o=t&&t*3,s=i&&i*2;t&&!e.hasOwnProperty(a)&&(e[a]=o),o&&e[a]<o&&(e[a]=o),i&&!e.hasOwnProperty(n)&&(e[n]=i*3),i&&e[n]<s&&(e[n]=s)}};var dt=function(r,e){var t=Ur(e[0].replace(\"#EXT-X-\",\"\")),i;Ti(e[1])?(i={},i=Object.assign(bi(e[1]),i)):i=lt(e[1]),r[t]=i},Ur=function(r){return r.toLowerCase().replace(/-(\\w)/g,function(e){return e[1].toUpperCase()})},lt=function(r){if(r.toLowerCase()===\"yes\"||r.toLowerCase()===\"no\")return r.toLowerCase()===\"yes\";var e=r.indexOf(\":\")!==-1?r:parseFloat(r);return isNaN(e)?r:e},gi=function(r){var e={},t=r.split(\"=\");if(t.length>1){var i=Ur(t[0]);e[i]=lt(t[1])}return e},bi=function(r){for(var e=r.split(\",\"),t={},i=0;e.length>i;i++){var a=e[i],n=gi(a);t=Object.assign(n,t)}return t},Ti=function(r){return r.indexOf(\"=\")>-1},wi=function(r,e){return e===-1?[r]:[r.substring(0,e),r.substring(e+1)]},Ei=function(r){var e={};if(r){var t=r.search(\",\"),i=r.slice(0,t),a=r.slice(t+1),n=[i,a];return n.forEach(function(o,s){for(var u=o.replace(/['\"]+/g,\"\").split(\"=\"),v=0;v<u.length;v++)u[v]===\"DATA-ID\"&&(e[\"DATA-ID\"]=u[1-v]),u[v]===\"VALUE\"&&(e.VALUE=u[1-v])}),{data:e}}},Fr=Fe;var ki={safeCall:ot,safeIncrement:O,getComputedStyle:st,secondsToMs:ut,assign:Object.assign,headersStringToObject:pe,cdnHeadersToRequestId:de,extractHostnameAndDomain:re,extractHostname:F,manifestParser:Fr,generateShortID:Oe,generateUUID:ee,now:A.now,findMediaElement:se},Vr=ki;var xi={PLAYER_READY:\"playerready\",VIEW_INIT:\"viewinit\",VIDEO_CHANGE:\"videochange\",PLAY:\"play\",PAUSE:\"pause\",PLAYING:\"playing\",TIME_UPDATE:\"timeupdate\",SEEKING:\"seeking\",SEEKED:\"seeked\",REBUFFER_START:\"rebufferstart\",REBUFFER_END:\"rebufferend\",ERROR:\"error\",ENDED:\"ended\",RENDITION_CHANGE:\"renditionchange\",ORIENTATION_CHANGE:\"orientationchange\",AD_REQUEST:\"adrequest\",AD_RESPONSE:\"adresponse\",AD_BREAK_START:\"adbreakstart\",AD_PLAY:\"adplay\",AD_PLAYING:\"adplaying\",AD_PAUSE:\"adpause\",AD_FIRST_QUARTILE:\"adfirstquartile\",AD_MID_POINT:\"admidpoint\",AD_THIRD_QUARTILE:\"adthirdquartile\",AD_ENDED:\"adended\",AD_BREAK_END:\"adbreakend\",AD_ERROR:\"aderror\",REQUEST_COMPLETED:\"requestcompleted\",REQUEST_FAILED:\"requestfailed\",REQUEST_CANCELLED:\"requestcanceled\",HEARTBEAT:\"hb\",DESTROY:\"destroy\"},Wr=xi;var Di=\"mux-embed\",Si=\"5.4.3\",Ri=\"2.1\",C={},ne=function(e){var t=arguments;typeof e==\"string\"?ne.hasOwnProperty(e)?be.default.setTimeout(function(){t=Array.prototype.splice.call(t,1),ne[e].apply(null,t)},0):q.warn(\"`\"+e+\"` is an unknown task\"):typeof e==\"function\"?be.default.setTimeout(function(){e(ne)},0):q.warn(\"`\"+e+\"` is invalid.\")},qi={loaded:A.now(),NAME:Di,VERSION:Si,API_VERSION:Ri,PLAYER_TRACKED:!1,monitor:function(e,t){return nt(ne,e,t)},destroyMonitor:function(e){var t=H(se(e),1),i=t[0];i&&i.mux&&typeof i.mux.destroy==\"function\"?i.mux.destroy():q.error(\"A video element monitor for `\"+e+\"` has not been initialized via `mux.monitor`.\")},addHLSJS:function(e,t){var i=G(e);C[i]?C[i].addHLSJS(t):q.error(\"A monitor for `\"+i+\"` has not been initialized.\")},addDashJS:function(e,t){var i=G(e);C[i]?C[i].addDashJS(t):q.error(\"A monitor for `\"+i+\"` has not been initialized.\")},removeHLSJS:function(e){var t=G(e);C[t]?C[t].removeHLSJS():q.error(\"A monitor for `\"+t+\"` has not been initialized.\")},removeDashJS:function(e){var t=G(e);C[t]?C[t].removeDashJS():q.error(\"A monitor for `\"+t+\"` has not been initialized.\")},init:function(e,t){ce()&&t&&t.respectDoNotTrack&&q.info(\"The browser's Do Not Track flag is enabled - Mux beaconing is disabled.\");var i=G(e);C[i]=new fr(ne,i,t)},emit:function(e,t,i){var a=G(e);C[a]?(C[a].emit(t,i),t===\"destroy\"&&delete C[a]):q.error(\"A monitor for `\"+a+\"` has not been initialized.\")},updateData:function(e,t){var i=G(e);C[i]?C[i].emit(\"hb\",t):q.error(\"A monitor for `\"+i+\"` has not been initialized.\")},setEmitTranslator:function(e,t){var i=G(e);C[i]?C[i].emitTranslator=t:q.error(\"A monitor for `\"+i+\"` has not been initialized.\")},setStateDataTranslator:function(e,t){var i=G(e);C[i]?C[i].stateDataTranslator=t:q.error(\"A monitor for `\"+i+\"` has not been initialized.\")},setGetPlayheadTime:function(e,t){var i=G(e);C[i]?C[i].getPlayheadTime=t:q.error(\"A monitor for `\"+i+\"` has not been initialized.\")},checkDoNotTrack:ce,log:q,utils:Vr,events:Wr,WINDOW_HIDDEN:!1,WINDOW_UNLOADING:!1};Object.assign(ne,qi);typeof be.default!=\"undefined\"&&typeof be.default.addEventListener==\"function\"&&be.default.addEventListener(\"pagehide\",function(r){r.persisted||(ne.WINDOW_UNLOADING=!0)},!1);var bd=ne;export{bd as default};\n/*!\n* JavaScript Cookie v2.1.3\n* https://github.com/js-cookie/js-cookie\n*\n* Copyright 2006, 2015 Klaus Hartl & Fagner Brack\n* Released under the MIT license\n*/\n", "import type { ValueOf, PlaybackCore, MuxMediaProps, MuxMediaPropsInternal, MuxMediaPropTypes } from './types';\nimport mux, { ErrorEvent } from 'mux-embed';\nimport Hls from './hls';\nimport type { HlsInterface } from './hls';\nimport { MediaError, MuxErrorCategory, MuxErrorCode, errorCategoryToTokenNameOrPrefix } from './errors';\nimport { setupAutoplay } from './autoplay';\nimport { setupPreload } from './preload';\nimport { setupMediaTracks } from './media-tracks';\nimport {\n  setupTextTracks,\n  addTextTrack,\n  removeTextTrack,\n  getTextTrack,\n  addCuePoints,\n  getCuePoints,\n  getActiveCuePoint,\n  setupCuePoints,\n  addChapters,\n  getChapters,\n  getActiveChapter,\n  setupChapters,\n} from './text-tracks';\nimport { getStartDate, getCurrentPdt } from './pdt';\nimport {\n  inSeekableRange,\n  toPlaybackIdParts,\n  getType,\n  toStreamTypeFromPlaylistType,\n  toTargetLiveWindowFromPlaylistType,\n  addEventListenerWithTeardown,\n  i18n,\n  parseJwt,\n} from './util';\nimport { StreamTypes, PlaybackTypes, ExtensionMimeTypeMap, CmcdTypes, HlsPlaylistTypes, MediaTypes } from './types';\nimport { ErrorDetails, ErrorTypes, type ErrorData, type HlsConfig } from 'hls.js';\nimport { getErrorFromResponse, MuxJWTAud } from './request-errors';\n// import { MediaKeySessionContext } from 'hls.js';\nexport {\n  mux,\n  Hls,\n  MediaError,\n  MuxErrorCategory,\n  MuxErrorCode,\n  errorCategoryToTokenNameOrPrefix,\n  MuxJWTAud,\n  addTextTrack,\n  removeTextTrack,\n  getTextTrack,\n  addCuePoints,\n  getCuePoints,\n  getActiveCuePoint,\n  setupCuePoints,\n  addChapters,\n  getChapters,\n  getActiveChapter,\n  setupChapters,\n  getStartDate,\n  getCurrentPdt,\n  toPlaybackIdParts,\n  i18n,\n  parseJwt,\n};\nexport * from './types';\n\nconst DRMType = {\n  FAIRPLAY: 'fairplay',\n  PLAYREADY: 'playready',\n  WIDEVINE: 'widevine',\n} as const;\n\ntype DRMTypeValue = (typeof DRMType)[keyof typeof DRMType];\nexport const toDRMTypeFromKeySystem = (keySystem: string): DRMTypeValue | undefined => {\n  if (keySystem.includes('fps')) return DRMType.FAIRPLAY;\n  if (keySystem.includes('playready')) return DRMType.PLAYREADY;\n  if (keySystem.includes('widevine')) return DRMType.WIDEVINE;\n  return undefined;\n};\n\nexport const getMediaPlaylistLinesFromMultivariantPlaylistSrc = async (src: string) => {\n  return fetch(src)\n    .then((resp) => {\n      if (resp.status !== 200) {\n        return Promise.reject(resp);\n      }\n      return resp.text();\n    })\n    .then((multivariantPlaylistStr) => {\n      const mediaPlaylistUrl = multivariantPlaylistStr.split('\\n').find((_line, idx, lines) => {\n        return idx && lines[idx - 1].startsWith('#EXT-X-STREAM-INF');\n      }) as string;\n\n      return fetch(mediaPlaylistUrl)\n        .then((resp) => {\n          if (resp.status !== 200) {\n            return Promise.reject(resp);\n          }\n          return resp.text();\n        })\n        .then((mediaPlaylistStr) => mediaPlaylistStr.split('\\n'));\n    });\n};\n\nexport const getStreamInfoFromPlaylistLines = (playlistLines: string[]) => {\n  const typeLine = playlistLines.find((line) => line.startsWith('#EXT-X-PLAYLIST-TYPE')) ?? '';\n  const playlistType = typeLine.split(':')[1]?.trim() as HlsPlaylistTypes;\n  const streamType = toStreamTypeFromPlaylistType(playlistType);\n  const targetLiveWindow = toTargetLiveWindowFromPlaylistType(playlistType);\n\n  // Computation of the live edge start offset per media-ui-extensions proposal. See: https://github.com/video-dev/media-ui-extensions/blob/main/proposals/0007-live-edge.md#recommended-computation-for-rfc8216bis12-aka-hls (CJP)\n  let liveEdgeStartOffset = undefined;\n\n  if (streamType === StreamTypes.LIVE) {\n    // Required if playlist contains one or more EXT-X-PART tags. See: https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis-12#section-4.4.3.7 (CJP)\n    const partInfLine = playlistLines.find((line) => line.startsWith('#EXT-X-PART-INF'));\n    const lowLatency = !!partInfLine;\n\n    if (lowLatency) {\n      // The EXT-X-PART-INF only has one in-spec named attribute, PART-TARGET, which is required,\n      // so parsing & casting presumptuously here. See spec link above for more info. (CJP)\n      const partTarget = +partInfLine.split(':')[1].split('=')[1];\n      liveEdgeStartOffset = partTarget * 2;\n    } else {\n      // This is required for all media playlists. See: https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis-12#section-4.4.3.1 (CJP)\n      const targetDurationLine = playlistLines.find((line) => line.startsWith('#EXT-X-TARGETDURATION')) as string;\n      // EXT-X-TARGETDURATION has exactly one unnamed attribute that represents the target duration value, which is required,\n      // so parsing and casting presumptuously here. See spec link above for more info. (CJP)\n      const targetDurationValue = targetDurationLine?.split(':')?.[1];\n      // NOTE: Defaulting here and using optional chaining above since some people are seeing RTEs on iPhones under edge cases.\n      // Identifying root cause would be ideal, but this will at least avoid the RTE. (CJP)\n      const targetDuration = +(targetDurationValue ?? 6);\n      liveEdgeStartOffset = targetDuration * 3;\n    }\n  }\n\n  return {\n    streamType,\n    targetLiveWindow,\n    liveEdgeStartOffset,\n  };\n};\n\nexport const getStreamInfoFromSrcAndType = async (src: string, type?: MediaTypes | '') => {\n  if (type === ExtensionMimeTypeMap.MP4) {\n    return {\n      streamType: StreamTypes.ON_DEMAND,\n      targetLiveWindow: Number.NaN,\n      liveEdgeStartOffset: undefined,\n    };\n  }\n\n  if (type === ExtensionMimeTypeMap.M3U8) {\n    const playlistLines = await getMediaPlaylistLinesFromMultivariantPlaylistSrc(src);\n    return getStreamInfoFromPlaylistLines(playlistLines);\n  }\n\n  // Unknown or undefined type.\n  console.error(`Media type ${type} is an unrecognized or unsupported type for src ${src}.`);\n  return {\n    streamType: undefined,\n    targetLiveWindow: undefined,\n    liveEdgeStartOffset: undefined,\n  };\n};\n\nexport const updateStreamInfoFromSrc = async (\n  src: string,\n  mediaEl: HTMLMediaElement,\n  type: MediaTypes | '' = getType({ src })\n) => {\n  const { streamType, targetLiveWindow, liveEdgeStartOffset } = await getStreamInfoFromSrcAndType(src, type);\n\n  (muxMediaState.get(mediaEl) ?? {}).liveEdgeStartOffset = liveEdgeStartOffset;\n\n  (muxMediaState.get(mediaEl) ?? {}).targetLiveWindow = targetLiveWindow;\n  mediaEl.dispatchEvent(new CustomEvent('targetlivewindowchange', { composed: true, bubbles: true }));\n\n  (muxMediaState.get(mediaEl) ?? {}).streamType = streamType;\n  mediaEl.dispatchEvent(new CustomEvent('streamtypechange', { composed: true, bubbles: true }));\n};\n\nexport const getStreamInfoFromHlsjsLevelDetails = (levelDetails: any) => {\n  const playlistType: HlsPlaylistTypes = levelDetails.type as HlsPlaylistTypes;\n\n  const streamType = toStreamTypeFromPlaylistType(playlistType);\n  const targetLiveWindow = toTargetLiveWindowFromPlaylistType(playlistType);\n  let liveEdgeStartOffset = undefined;\n  const lowLatency = !!levelDetails.partList?.length;\n  if (streamType === StreamTypes.LIVE) {\n    liveEdgeStartOffset = lowLatency ? levelDetails.partTarget * 2 : levelDetails.targetduration * 3;\n  }\n\n  return {\n    streamType,\n    targetLiveWindow,\n    liveEdgeStartOffset,\n    lowLatency,\n  };\n};\n\nexport const updateStreamInfoFromHlsjsLevelDetails = (\n  levelDetails: any,\n  mediaEl: HTMLMediaElement,\n  hls: Pick<Hls, 'config' | 'userConfig' | 'liveSyncPosition'>\n) => {\n  const { streamType, targetLiveWindow, liveEdgeStartOffset, lowLatency } =\n    getStreamInfoFromHlsjsLevelDetails(levelDetails);\n\n  if (streamType === StreamTypes.LIVE) {\n    // Update hls.js config for live/ll-live\n    if (lowLatency) {\n      hls.config.backBufferLength = hls.userConfig.backBufferLength ?? 4;\n      hls.config.maxFragLookUpTolerance = hls.userConfig.maxFragLookUpTolerance ?? 0.001;\n      // For ll-hls, ensure that up switches are weighted the same as down switches to mitigate\n      // cases of getting stuck at lower bitrates.\n      hls.config.abrBandWidthUpFactor = hls.userConfig.abrBandWidthUpFactor ?? hls.config.abrBandWidthFactor;\n    } else {\n      hls.config.backBufferLength = hls.userConfig.backBufferLength ?? 8;\n    }\n\n    // Proxy `seekable.end()` to constrain based on rules in\n    // https://github.com/video-dev/media-ui-extensions/blob/main/proposals/0007-live-edge.md#property-constraint-on-htmlmediaelementseekableend-to-model-seekable-live-edge\n    const seekable: TimeRanges = Object.freeze({\n      get length() {\n        return mediaEl.seekable.length;\n      },\n      start(index: number) {\n        return mediaEl.seekable.start(index);\n      },\n      end(index: number) {\n        // Defer to native seekable for:\n        // 1) \"out of range\" cases\n        // 2) \"finite duration\" media (whether live/\"DVR\" that has ended or on demand)\n        if (index > this.length || index < 0 || Number.isFinite(mediaEl.duration)) return mediaEl.seekable.end(index);\n        // Otherwise rely on the live sync position (but still fall back to native seekable when nullish)\n        return hls.liveSyncPosition ?? mediaEl.seekable.end(index);\n      },\n    });\n    (muxMediaState.get(mediaEl) ?? {}).seekable = seekable;\n  }\n\n  (muxMediaState.get(mediaEl) ?? {}).liveEdgeStartOffset = liveEdgeStartOffset;\n\n  (muxMediaState.get(mediaEl) ?? {}).targetLiveWindow = targetLiveWindow;\n  mediaEl.dispatchEvent(new CustomEvent('targetlivewindowchange', { composed: true, bubbles: true }));\n\n  (muxMediaState.get(mediaEl) ?? {}).streamType = streamType;\n  mediaEl.dispatchEvent(new CustomEvent('streamtypechange', { composed: true, bubbles: true }));\n};\n\ndeclare global {\n  interface NavigatorUAData {\n    platform: string;\n    mobile: boolean;\n    brands: Array<{ brand: string; version: string }>;\n  }\n\n  interface Navigator {\n    userAgentData?: NavigatorUAData;\n  }\n}\n\nconst userAgentStr = globalThis?.navigator?.userAgent ?? '';\nconst userAgentPlatform = globalThis?.navigator?.userAgentData?.platform ?? '';\n\n// NOTE: Our primary *goal* with this is to detect \"non-Apple-OS\" platforms which may also support\n// native HLS playback. Our primary concern with any check for this is \"false negatives\" where we\n// identify an \"Apple-OS\" as a \"non-Apple-OS\". As such, instead of having logic to attempt to identify\n// \"!isAppleOS\", we opt to target known platforms that can support both native playback and MSE/hls.js.\n// For now, these are \"Android or Android-like\" platforms. If we end up matching platforms other than\n// Android (or e.g. forks thereof), this is fine so long as it doesn't include Apple-OS platforms.\n// Below are two strategies:\n// 1. UA string parsing - here, we're extra cautious to only match if the UA string explicitly includes 'android'.\n//   This is prone to false negatives (aka \"Android or Android-like\" platforms that yield false), since\n//   detection using UA strings is intentionally and notoriously unreliable (See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent)\n//   and Google is even officially attempting to lock this down even more for security and privacy reasons\n//   (See: https://developers.google.com/privacy-sandbox/blog/user-agent-reduction-android-model-and-version)\n// 2. userAgentData.platform checking - here, we're matching either 'android' or 'x11', and could add more matches in the future\n//    While still prone to false negatives, we can be a bit more aggressive with matches here for a few reasons.\n//    First, navigator.userAgentData is still experimental, is only supported on a subset of Chromium browsers,\n//    and neither Mozilla nor Webkit have even established an official browser support position. In other words,\n//    Apple-OS Safari and even other Apple-OS browsers (including Chrome) will typically not even support this\n//    feature, and, if and when they do, the purpose of this new API is to avoid obfuscatory information, so\n//    we should be able to better trust userAgentData.platform to not result in erroneous matches.\nconst isAndroidLike =\n  userAgentStr.toLowerCase().includes('android') ||\n  ['x11', 'android'].some((platformStr) => userAgentPlatform.toLowerCase().includes(platformStr));\n\n// NOTE: Exporting for testing\nexport const muxMediaState: WeakMap<\n  HTMLMediaElement,\n  Partial<MuxMediaProps> & { seekable?: TimeRanges; liveEdgeStartOffset?: number }\n> = new WeakMap();\n\nconst MUX_VIDEO_DOMAIN = 'mux.com';\nconst MSE_SUPPORTED = Hls.isSupported?.();\nconst DEFAULT_PREFER_MSE = isAndroidLike;\n\nexport const generatePlayerInitTime = () => {\n  return mux.utils.now();\n};\n\nexport const generateUUID = mux.utils.generateUUID;\n\ntype MuxVideoURLProps = Partial<\n  Pick<\n    MuxMediaPropTypes,\n    | 'playbackId'\n    | 'customDomain'\n    | 'maxResolution'\n    | 'minResolution'\n    | 'renditionOrder'\n    | 'programStartTime'\n    | 'programEndTime'\n    | 'assetStartTime'\n    | 'assetEndTime'\n    | 'tokens'\n    | 'playbackToken'\n    | 'extraSourceParams'\n  >\n>;\n\nexport const toMuxVideoURL = ({\n  playbackId: playbackIdWithParams,\n  customDomain: domain = MUX_VIDEO_DOMAIN,\n  maxResolution,\n  minResolution,\n  renditionOrder,\n  programStartTime,\n  programEndTime,\n  assetStartTime,\n  assetEndTime,\n  // Normalizes different ways of providing playback token\n  playbackToken,\n  tokens: { playback: token = playbackToken } = {},\n  extraSourceParams = {},\n}: MuxVideoURLProps = {}) => {\n  if (!playbackIdWithParams) return undefined;\n  // Normalizes different ways of providing playback id\n  const [playbackId, queryPart = ''] = toPlaybackIdParts(playbackIdWithParams);\n  const url = new URL(`https://stream.${domain}/${playbackId}.m3u8${queryPart}`);\n  /*\n   * All identified query params here can only be added to public\n   * playback IDs. In order to use these features with signed URLs\n   * the query param must be added to the signing token.\n   *\n   * */\n  if (token || url.searchParams.has('token')) {\n    url.searchParams.forEach((_, key) => {\n      if (key != 'token') url.searchParams.delete(key);\n    });\n    if (token) url.searchParams.set('token', token);\n  } else {\n    if (maxResolution) {\n      url.searchParams.set('max_resolution', maxResolution);\n    }\n    if (minResolution) {\n      url.searchParams.set('min_resolution', minResolution);\n      if (maxResolution && +maxResolution.slice(0, -1) < +minResolution.slice(0, -1)) {\n        console.error(\n          'minResolution must be <= maxResolution',\n          'minResolution',\n          minResolution,\n          'maxResolution',\n          maxResolution\n        );\n      }\n    }\n    if (renditionOrder) {\n      url.searchParams.set('rendition_order', renditionOrder);\n    }\n    if (programStartTime) {\n      url.searchParams.set('program_start_time', `${programStartTime}`);\n    }\n    if (programEndTime) {\n      url.searchParams.set('program_end_time', `${programEndTime}`);\n    }\n    if (assetStartTime) {\n      url.searchParams.set('asset_start_time', `${assetStartTime}`);\n    }\n    if (assetEndTime) {\n      url.searchParams.set('asset_end_time', `${assetEndTime}`);\n    }\n    Object.entries(extraSourceParams).forEach(([k, v]) => {\n      if (v == undefined) return;\n      url.searchParams.set(k, v);\n    });\n  }\n  return url.toString();\n};\n\nconst toPlaybackIdFromParameterized = (playbackIdWithParams: string | undefined) => {\n  if (!playbackIdWithParams) return undefined;\n  const [playbackId] = playbackIdWithParams.split('?');\n  // `|| undefined` is here to handle potential invalid cases\n  return playbackId || undefined;\n};\n\nexport const toPlaybackIdFromSrc = (src: string | undefined) => {\n  if (!src || !src.startsWith('https://stream.')) return undefined;\n  const [playbackId] = new URL(src).pathname.slice(1).split('.m3u8');\n  // `|| undefined` is here to handle potential invalid cases\n  return playbackId || undefined;\n};\n\nconst toVideoId = (props: Partial<MuxMediaPropsInternal>) => {\n  if (props?.metadata?.video_id) return props.metadata.video_id;\n  if (!isMuxVideoSrc(props)) return props.src;\n  return toPlaybackIdFromParameterized(props.playbackId) ?? toPlaybackIdFromSrc(props.src) ?? props.src;\n};\n\nexport const getError = (mediaEl: HTMLMediaElement) => {\n  return muxMediaState.get(mediaEl)?.error;\n};\n\nexport const getStreamType = (mediaEl: HTMLMediaElement) => {\n  return muxMediaState.get(mediaEl)?.streamType ?? StreamTypes.UNKNOWN;\n};\n\nexport const getTargetLiveWindow = (mediaEl: HTMLMediaElement) => {\n  return muxMediaState.get(mediaEl)?.targetLiveWindow ?? Number.NaN;\n};\n\nexport const getSeekable = (mediaEl: HTMLMediaElement) => {\n  return muxMediaState.get(mediaEl)?.seekable ?? mediaEl.seekable;\n};\n\nexport const getLiveEdgeStart = (mediaEl: HTMLMediaElement) => {\n  const liveEdgeStartOffset = muxMediaState.get(mediaEl)?.liveEdgeStartOffset;\n  if (typeof liveEdgeStartOffset !== 'number') return Number.NaN;\n  const seekable = getSeekable(mediaEl);\n  // We aren't guaranteed that seekable is ready before invoking this, so handle that case.\n  if (!seekable.length) return Number.NaN;\n  return seekable.end(seekable.length - 1) - liveEdgeStartOffset;\n};\n\nconst DEFAULT_ENDED_MOE = 0.034;\n\nconst isApproximatelyEqual = (x: number, y: number, moe = DEFAULT_ENDED_MOE) => Math.abs(x - y) <= moe;\nconst isApproximatelyGTE = (x: number, y: number, moe = DEFAULT_ENDED_MOE) => x > y || isApproximatelyEqual(x, y, moe);\n\nexport const isPseudoEnded = (mediaEl: HTMLMediaElement, moe = DEFAULT_ENDED_MOE) => {\n  return mediaEl.paused && isApproximatelyGTE(mediaEl.currentTime, mediaEl.duration, moe);\n};\n\nexport const isStuckOnLastFragment = (\n  mediaEl: HTMLMediaElement,\n  hls?: Pick<\n    Hls,\n    /** Should we add audio fragments logic here, too? (CJP) */\n    // | 'audioTrack'\n    // | 'audioTracks'\n    'levels' | 'currentLevel'\n  >\n) => {\n  if (!hls || !mediaEl.buffered.length) return undefined;\n  if (mediaEl.readyState > 2) return false;\n  const videoLevelDetails =\n    hls.currentLevel >= 0\n      ? hls.levels?.[hls.currentLevel]?.details\n      : hls.levels.find((level) => !!level.details)?.details;\n\n  // Don't define for live streams (for now).\n  if (!videoLevelDetails || videoLevelDetails.live) return undefined;\n\n  const { fragments } = videoLevelDetails;\n\n  // Don't give a definitive true|false before we have no fragments (for now).\n  if (!fragments?.length) return undefined;\n\n  // Do a cheap check up front to see if we're close to the end.\n  // For more on TARGET_DURATION, see https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis-14#section-4.4.3.1 (CJP)\n  if (mediaEl.currentTime < mediaEl.duration - (videoLevelDetails.targetduration + 0.5)) return false;\n\n  const lastFragment = fragments[fragments.length - 1];\n\n  // We're not yet playing the last fragment, so we can't be stuck on it.\n  if (mediaEl.currentTime <= lastFragment.start) return false;\n\n  const lastFragmentMidpoint = lastFragment.start + lastFragment.duration / 2;\n  const lastBufferedStart = mediaEl.buffered.start(mediaEl.buffered.length - 1);\n  const lastBufferedEnd = mediaEl.buffered.end(mediaEl.buffered.length - 1);\n\n  // True if we've already buffered (half of) the last fragment\n  const lastFragmentInBuffer = lastFragmentMidpoint > lastBufferedStart && lastFragmentMidpoint < lastBufferedEnd;\n  // If we haven't buffered half already, assume we're still waiting to fetch+buffer the fragment, otherwise,\n  // since we already checked the ready state, this means we're stuck on the last segment, and should pretend we're ended!\n  return lastFragmentInBuffer;\n};\n\nexport const getEnded = (\n  mediaEl: HTMLMediaElement,\n  hls?: Pick<\n    Hls,\n    /** Should we add audio fragments logic here, too? (CJP) */\n    // | 'audioTrack'\n    // | 'audioTracks'\n    'levels' | 'currentLevel'\n  >\n) => {\n  // Since looping media never truly ends, don't apply pseudo-ended logic\n  // Also, trust when the HTMLMediaElement says we have ended (only apply pseudo-ended logic when it reports false)\n  if (mediaEl.ended || mediaEl.loop) return mediaEl.ended;\n  // Externalize conversion to boolean for \"under-determined cases\" here (See isStuckOnLastFragment() for details)\n  if (hls && !!isStuckOnLastFragment(mediaEl, hls)) return true;\n  return isPseudoEnded(mediaEl);\n};\n\nexport const initialize = (props: Partial<MuxMediaPropsInternal>, mediaEl: HTMLMediaElement, core?: PlaybackCore) => {\n  // Automatically tear down previously initialized mux data & hls instance if it exists.\n  teardown(mediaEl, core);\n  // NOTE: metadata should never be nullish/nil. Adding here for type safety due to current type defs.\n  const { metadata = {} } = props;\n  const { view_session_id = generateUUID() } = metadata;\n  const video_id = toVideoId(props);\n  metadata.view_session_id = view_session_id;\n  metadata.video_id = video_id;\n  props.metadata = metadata;\n\n  // Used to signal DRM Type to Mux Data. See, e.g. `getDRMConfig()`\n  const drmTypeCb = (drmType?: string) => {\n    mediaEl.mux?.emit('hb', { view_drm_type: drmType });\n  };\n\n  props.drmTypeCb = drmTypeCb;\n\n  muxMediaState.set(mediaEl as HTMLMediaElement, {});\n  const nextHlsInstance = setupHls(props, mediaEl);\n  const setPreload = setupPreload(props as Pick<MuxMediaProps, 'preload' | 'src'>, mediaEl, nextHlsInstance);\n  setupMux(props, mediaEl, nextHlsInstance);\n  loadMedia(props, mediaEl, nextHlsInstance);\n  setupCuePoints(mediaEl);\n  setupChapters(mediaEl);\n  const setAutoplay = setupAutoplay(props as Pick<MuxMediaProps, 'autoplay'>, mediaEl, nextHlsInstance);\n\n  return {\n    engine: nextHlsInstance,\n    setAutoplay,\n    setPreload,\n  };\n};\n\nexport const teardown = (mediaEl?: HTMLMediaElement | null, core?: PlaybackCore) => {\n  const hls = core?.engine;\n  if (hls) {\n    hls.detachMedia();\n    hls.destroy();\n  }\n  if (mediaEl?.mux && !mediaEl.mux.deleted) {\n    mediaEl.mux.destroy();\n    delete mediaEl.mux;\n  }\n  if (mediaEl) {\n    mediaEl.removeAttribute('src');\n    mediaEl.load();\n    mediaEl.removeEventListener('error', handleNativeError);\n    mediaEl.removeEventListener('error', handleInternalError);\n    mediaEl.removeEventListener('durationchange', seekInSeekableRange);\n    muxMediaState.delete(mediaEl);\n    mediaEl.dispatchEvent(new Event('teardown'));\n  }\n};\n\n/**\n * Returns true if we should use native playback. e.g. progressive files (mp3, mp4, webm) or native HLS on Safari.\n * We should use native playback for hls media sources if we\n *\n *   a) can use native playback (excluding Android, it's MSE by default)\n *   b) not prefer to use MSE/hls.js if it's supported\n */\nfunction useNative(\n  props: Partial<Pick<MuxMediaProps, 'preferPlayback' | 'type'>>,\n  mediaEl: Pick<HTMLMediaElement, 'canPlayType'>\n) {\n  const type = getType(props);\n  const hlsType = type === ExtensionMimeTypeMap.M3U8;\n  if (!hlsType) return true;\n\n  const canUseNative = !type || (mediaEl.canPlayType(type) ?? true);\n  const { preferPlayback } = props;\n\n  const preferMse = preferPlayback === PlaybackTypes.MSE;\n  const preferNative = preferPlayback === PlaybackTypes.NATIVE;\n  const forceMse = MSE_SUPPORTED && (preferMse || DEFAULT_PREFER_MSE);\n\n  return canUseNative && (preferNative || !forceMse);\n}\n\nexport const setupHls = (\n  props: Partial<\n    Pick<\n      MuxMediaPropsInternal,\n      'debug' | 'streamType' | 'type' | 'startTime' | 'metadata' | 'preferCmcd' | '_hlsConfig' | 'tokens' | 'drmTypeCb'\n    >\n  >,\n  mediaEl: Pick<HTMLMediaElement, 'canPlayType'>\n) => {\n  const { debug, streamType, startTime: startPosition = -1, metadata, preferCmcd, _hlsConfig = {} } = props;\n  const type = getType(props);\n  const hlsType = type === ExtensionMimeTypeMap.M3U8;\n  const shouldUseNative = useNative(props, mediaEl);\n\n  // 1. if we are trying to play an hls media source create hls if we should be using it \"under the hood\"\n  if (hlsType && !shouldUseNative && MSE_SUPPORTED) {\n    const defaultConfig = {\n      backBufferLength: 30,\n      renderTextTracksNatively: false,\n      liveDurationInfinity: true,\n      capLevelToPlayerSize: true,\n      capLevelOnFPSDrop: true,\n    };\n    const streamTypeConfig = getStreamTypeConfig(streamType);\n    const drmConfig = getDRMConfig(props);\n    // NOTE: `metadata.view_session_id` & `metadata.video_id` are guaranteed here (CJP)\n    const cmcd =\n      preferCmcd !== CmcdTypes.NONE\n        ? {\n            useHeaders: preferCmcd === CmcdTypes.HEADER,\n            sessionId: metadata?.view_session_id,\n            contentId: metadata?.video_id,\n          }\n        : undefined;\n    const hls = new Hls({\n      // Kind of like preload metadata, but causes spinner.\n      // autoStartLoad: false,\n      debug,\n      startPosition,\n      cmcd,\n      xhrSetup: (xhr, url) => {\n        if (preferCmcd && preferCmcd !== CmcdTypes.QUERY) return;\n        const urlObj = new URL(url);\n        if (!urlObj.searchParams.has('CMCD')) return;\n        const cmcdVal = (urlObj.searchParams.get('CMCD')?.split(',') ?? [])\n          .filter((cmcdKVStr) => cmcdKVStr.startsWith('sid') || cmcdKVStr.startsWith('cid'))\n          .join(',');\n        urlObj.searchParams.set('CMCD', cmcdVal);\n\n        xhr.open('GET', urlObj);\n      },\n      ...defaultConfig,\n      ...streamTypeConfig,\n      ...drmConfig,\n      ..._hlsConfig,\n    }) as HlsInterface;\n\n    return hls;\n  }\n  return undefined;\n};\n\nexport const getStreamTypeConfig = (streamType?: ValueOf<StreamTypes>) => {\n  // for regular live videos, set backBufferLength to 8\n  if (streamType === StreamTypes.LIVE) {\n    const liveConfig = {\n      backBufferLength: 8,\n    };\n\n    return liveConfig;\n  }\n\n  return {};\n};\n\nexport const getDRMConfig = (\n  props: Partial<Pick<MuxMediaPropsInternal, 'src' | 'playbackId' | 'tokens' | 'customDomain' | 'drmTypeCb'>>\n): Partial<HlsConfig> => {\n  const {\n    tokens: { drm: drmToken } = {},\n    playbackId: playbackIdWithOptionalParams, // Since Mux Player typically sets `src` instead of `playbackId`, fall back to it here (CJP)\n    drmTypeCb,\n  } = props;\n  const playbackId = toPlaybackIdFromParameterized(playbackIdWithOptionalParams);\n  if (!drmToken || !playbackId) return {};\n  return {\n    emeEnabled: true,\n    drmSystems: {\n      'com.apple.fps': {\n        licenseUrl: toLicenseKeyURL(props, 'fairplay'),\n        serverCertificateUrl: toAppCertURL(props, 'fairplay'),\n      },\n      'com.widevine.alpha': {\n        licenseUrl: toLicenseKeyURL(props, 'widevine'),\n      },\n      'com.microsoft.playready': {\n        licenseUrl: toLicenseKeyURL(props, 'playready'),\n      },\n    },\n    requestMediaKeySystemAccessFunc: (keySystem, supportedConfigurations) => {\n      if (keySystem === 'com.widevine.alpha') {\n        supportedConfigurations = [\n          // NOTE: For widevine, by default we'll duplicate the key system configs but add L1-level\n          // security to the first set of duplicates so the key system will \"prefer\" that\n          // if/when available. (CJP)\n          // See, e.g.: https://developer.mozilla.org/en-US/docs/Web/API/Navigator/requestMediaKeySystemAccess#supportedconfigurations\n          ...supportedConfigurations.map((mediaKeySystemConfig) => {\n            const videoCapabilities = mediaKeySystemConfig.videoCapabilities?.map((capability) => {\n              return {\n                ...capability,\n                robustness: 'HW_SECURE_ALL',\n              };\n            });\n            return {\n              ...mediaKeySystemConfig,\n              videoCapabilities,\n            };\n          }),\n          ...supportedConfigurations,\n        ];\n      }\n      return navigator.requestMediaKeySystemAccess(keySystem, supportedConfigurations).then((value) => {\n        const drmType = toDRMTypeFromKeySystem(keySystem);\n        drmTypeCb?.(drmType);\n        return value;\n      });\n    },\n  };\n};\n\nexport const getAppCertificate = async (appCertificateUrl: string) => {\n  const resp = await fetch(appCertificateUrl);\n  if (resp.status !== 200) {\n    return Promise.reject(resp);\n  }\n  const body = await resp.arrayBuffer();\n  return body;\n};\n\nexport const getLicenseKey = async (message: ArrayBuffer, licenseServerUrl: string) => {\n  const resp = await fetch(licenseServerUrl, {\n    method: 'POST',\n    headers: { 'Content-type': 'application/octet-stream' },\n    body: message,\n  });\n  if (resp.status !== 200) {\n    return Promise.reject(resp);\n  }\n  const keyBuffer = await resp.arrayBuffer();\n  return new Uint8Array(keyBuffer);\n};\n\nexport const setupNativeFairplayDRM = (\n  props: Partial<Pick<MuxMediaPropsInternal, 'playbackId' | 'tokens' | 'playbackToken' | 'customDomain' | 'drmTypeCb'>>,\n  mediaEl: HTMLMediaElement\n) => {\n  const onFpEncrypted = async (event: MediaEncryptedEvent) => {\n    try {\n      const initDataType = event.initDataType;\n      if (initDataType !== 'skd') {\n        console.error(`Received unexpected initialization data type \"${initDataType}\"`);\n        return;\n      }\n\n      if (!mediaEl.mediaKeys) {\n        const access = await navigator\n          .requestMediaKeySystemAccess('com.apple.fps', [\n            {\n              initDataTypes: [initDataType],\n              videoCapabilities: [{ contentType: 'application/vnd.apple.mpegurl', robustness: '' }],\n              distinctiveIdentifier: 'not-allowed',\n              persistentState: 'not-allowed',\n              sessionTypes: ['temporary'],\n            },\n          ])\n          .then((value) => {\n            props.drmTypeCb?.(DRMType.FAIRPLAY);\n            return value;\n          })\n          .catch(() => {\n            const message = i18n(\n              'Cannot play DRM-protected content with current security configuration on this browser. Try playing in another browser.'\n            );\n            // Should we flag this as a business exception?\n            const mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, true);\n            mediaError.errorCategory = MuxErrorCategory.DRM;\n            mediaError.muxCode = MuxErrorCode.ENCRYPTED_UNSUPPORTED_KEY_SYSTEM;\n            mediaEl.dispatchEvent(\n              new CustomEvent('error', {\n                detail: mediaError,\n              })\n            );\n          });\n\n        if (!access) return;\n\n        const keys = await access.createMediaKeys();\n\n        try {\n          const fairPlayAppCert = await getAppCertificate(toAppCertURL(props, 'fairplay')).catch((errOrResp) => {\n            if (errOrResp instanceof Response) {\n              const mediaError = getErrorFromResponse(errOrResp, MuxErrorCategory.DRM, props);\n              console.error('mediaError', mediaError?.message, mediaError?.context);\n              if (mediaError) {\n                return Promise.reject(mediaError);\n              }\n              // NOTE: This should never happen. Adding for exhaustiveness (CJP).\n              return Promise.reject(new Error('Unexpected error in app cert request'));\n            }\n            return Promise.reject(errOrResp);\n          });\n          await keys.setServerCertificate(fairPlayAppCert).catch(() => {\n            const message = i18n(\n              'Your server certificate failed when attempting to set it. This may be an issue with a no longer valid certificate.'\n            );\n            const mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, true);\n            mediaError.errorCategory = MuxErrorCategory.DRM;\n            mediaError.muxCode = MuxErrorCode.ENCRYPTED_UPDATE_SERVER_CERT_FAILED;\n            return Promise.reject(mediaError);\n          });\n          // @ts-ignore\n        } catch (error: Error | MediaError) {\n          mediaEl.dispatchEvent(\n            new CustomEvent('error', {\n              detail: error,\n            })\n          );\n          return;\n        }\n        await mediaEl.setMediaKeys(keys);\n      }\n\n      const initData = event.initData;\n      if (initData == null) {\n        console.error(`Could not start encrypted playback due to missing initData in ${event.type} event`);\n        return;\n      }\n\n      const session = (mediaEl.mediaKeys as MediaKeys).createSession();\n      session.addEventListener('keystatuseschange', () => {\n        // recheck key statuses\n        // NOTE: As an improvement, we could also add checks for a status of 'expired' and\n        // attempt to renew the license here (CJP)\n        session.keyStatuses.forEach((mediaKeyStatus) => {\n          let mediaError;\n          if (mediaKeyStatus === 'internal-error') {\n            const message = i18n(\n              'The DRM Content Decryption Module system had an internal failure. Try reloading the page, upading your browser, or playing in another browser.'\n            );\n            mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, true);\n            mediaError.errorCategory = MuxErrorCategory.DRM;\n            mediaError.muxCode = MuxErrorCode.ENCRYPTED_CDM_ERROR;\n          } else if (mediaKeyStatus === 'output-restricted' || mediaKeyStatus === 'output-downscaled') {\n            const message = i18n(\n              'DRM playback is being attempted in an environment that is not sufficiently secure. User may see black screen.'\n            );\n            // NOTE: When encountered, this is a non-fatal error (though it's certainly interruptive of standard playback experience). (CJP)\n            mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, false);\n            mediaError.errorCategory = MuxErrorCategory.DRM;\n            mediaError.muxCode = MuxErrorCode.ENCRYPTED_OUTPUT_RESTRICTED;\n          }\n\n          if (mediaError) {\n            mediaEl.dispatchEvent(\n              new CustomEvent('error', {\n                detail: mediaError,\n              })\n            );\n          }\n        });\n      });\n      const message = await Promise.all([\n        session.generateRequest(initDataType, initData).catch(() => {\n          // eslint-disable-next-line no-shadow\n          const message = i18n(\n            'Failed to generate a DRM license request. This may be an issue with the player or your protected content.'\n          );\n          const mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, true);\n          mediaError.errorCategory = MuxErrorCategory.DRM;\n          mediaError.muxCode = MuxErrorCode.ENCRYPTED_GENERATE_REQUEST_FAILED;\n          mediaEl.dispatchEvent(\n            new CustomEvent('error', {\n              detail: mediaError,\n            })\n          );\n        }),\n        new Promise<MediaKeyMessageEvent['message']>((resolve) => {\n          session.addEventListener(\n            'message',\n            (messageEvent) => {\n              resolve(messageEvent.message);\n            },\n            { once: true }\n          );\n        }),\n      ]).then(([, messageEventMsg]) => messageEventMsg);\n      session.generateRequest(initDataType, initData);\n\n      const response = await getLicenseKey(message, toLicenseKeyURL(props, 'fairplay')).catch((errOrResp) => {\n        if (errOrResp instanceof Response) {\n          const mediaError = getErrorFromResponse(errOrResp, MuxErrorCategory.DRM, props);\n          console.error('mediaError', mediaError?.message, mediaError?.context);\n          if (mediaError) {\n            return Promise.reject(mediaError);\n          }\n          // NOTE: This should never happen. Adding for exhaustiveness (CJP).\n          return Promise.reject(new Error('Unexpected error in license key request'));\n        }\n        return Promise.reject(errOrResp);\n      });\n      await session.update(response).catch(() => {\n        // eslint-disable-next-line no-shadow\n        const message = i18n(\n          'Failed to update DRM license. This may be an issue with the player or your protected content.'\n        );\n        const mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, true);\n        mediaError.errorCategory = MuxErrorCategory.DRM;\n        mediaError.muxCode = MuxErrorCode.ENCRYPTED_UPDATE_LICENSE_FAILED;\n        return Promise.reject(mediaError);\n      });\n      // @ts-ignore\n    } catch (error: Error | MediaError) {\n      mediaEl.dispatchEvent(\n        new CustomEvent('error', {\n          detail: error,\n        })\n      );\n      return;\n    }\n  };\n\n  addEventListenerWithTeardown(mediaEl, 'encrypted', onFpEncrypted);\n};\n\nexport const toLicenseKeyURL = (\n  {\n    playbackId: playbackIdWithParams,\n    tokens: { drm: token } = {},\n    customDomain = MUX_VIDEO_DOMAIN,\n  }: Partial<Pick<MuxMediaPropsInternal, 'playbackId' | 'tokens' | 'customDomain'>>,\n  scheme: 'widevine' | 'playready' | 'fairplay'\n) => {\n  const playbackId = toPlaybackIdFromParameterized(playbackIdWithParams);\n  // NOTE: Mux Video currently doesn't support custom domains for license/DRM endpoints, but\n  // customDomain can also be used for internal use cases, so treat that as an exception case for now. (CJP)\n  const domain = customDomain.toLocaleLowerCase().endsWith(MUX_VIDEO_DOMAIN) ? customDomain : MUX_VIDEO_DOMAIN;\n  return `https://license.${domain}/license/${scheme}/${playbackId}?token=${token}`;\n};\n\nexport const toAppCertURL = (\n  {\n    playbackId: playbackIdWithParams,\n    tokens: { drm: token } = {},\n    customDomain = MUX_VIDEO_DOMAIN,\n  }: Partial<Pick<MuxMediaPropsInternal, 'playbackId' | 'tokens' | 'customDomain'>>,\n  scheme: 'widevine' | 'playready' | 'fairplay'\n) => {\n  const playbackId = toPlaybackIdFromParameterized(playbackIdWithParams);\n  // NOTE: Mux Video currently doesn't support custom domains for license/DRM endpoints, but\n  // customDomain can also be used for internal use cases, so treat that as an exception case for now. (CJP)\n  const domain = customDomain.toLocaleLowerCase().endsWith(MUX_VIDEO_DOMAIN) ? customDomain : MUX_VIDEO_DOMAIN;\n  return `https://license.${domain}/appcert/${scheme}/${playbackId}?token=${token}`;\n};\n\nexport const isMuxVideoSrc = ({\n  playbackId,\n  src,\n  customDomain,\n}: Partial<Pick<MuxMediaPropsInternal, 'playbackId' | 'src' | 'customDomain'>>) => {\n  if (!!playbackId) return true;\n  // having no playback id and no src string should never actually happen, but could\n  if (typeof src !== 'string') return false;\n  // Include base for relative paths\n  const base = window?.location.href;\n  const hostname = new URL(src, base).hostname.toLocaleLowerCase();\n\n  return hostname.includes(MUX_VIDEO_DOMAIN) || (!!customDomain && hostname.includes(customDomain.toLocaleLowerCase()));\n};\n\nexport const setupMux = (\n  props: Partial<\n    Pick<\n      MuxMediaPropsInternal,\n      | 'envKey'\n      | 'playerInitTime'\n      | 'beaconCollectionDomain'\n      | 'errorTranslator'\n      | 'metadata'\n      | 'debug'\n      | 'playerSoftwareName'\n      | 'playerSoftwareVersion'\n      | 'playbackId'\n      | 'src'\n      | 'customDomain'\n      | 'disableCookies'\n      | 'disableTracking'\n    >\n  >,\n  mediaEl: HTMLMediaElement,\n  hlsjs?: HlsInterface\n) => {\n  const { envKey: env_key, disableTracking } = props;\n  const inferredEnv = isMuxVideoSrc(props);\n\n  if (!disableTracking && (env_key || inferredEnv)) {\n    const {\n      playerInitTime: player_init_time,\n      playerSoftwareName: player_software_name,\n      playerSoftwareVersion: player_software_version,\n      beaconCollectionDomain,\n      debug,\n      disableCookies,\n    } = props;\n\n    const metadata = {\n      ...props.metadata,\n      video_title: props?.metadata?.video_title || undefined,\n    };\n\n    const muxEmbedErrorTranslator = (error: ErrorEvent) => {\n      // mux-embed auto tracks fatal hls.js errors, turn it off.\n      // playback-core will emit errors with a numeric code manually to mux-embed.\n      if (typeof error.player_error_code === 'string') return false;\n\n      if (typeof props.errorTranslator === 'function') {\n        return props.errorTranslator(error);\n      }\n\n      return error;\n    };\n\n    mux.monitor(mediaEl, {\n      debug,\n      beaconCollectionDomain,\n      hlsjs,\n      Hls: hlsjs ? Hls : undefined,\n      automaticErrorTracking: false,\n      errorTranslator: muxEmbedErrorTranslator,\n      disableCookies,\n      data: {\n        ...(env_key ? { env_key } : {}),\n        // Metadata fields\n        player_software_name,\n        // NOTE: Adding this because there appears to be some instability on whether\n        // player_software_name or player_software \"wins\" for Mux Data (CJP)\n        player_software: player_software_name,\n        player_software_version,\n        player_init_time,\n        // Use any metadata passed in programmatically (which may override the defaults above)\n        ...metadata,\n      },\n    });\n  }\n};\n\nexport const loadMedia = (\n  props: Partial<\n    Pick<\n      MuxMediaProps,\n      | 'preferPlayback'\n      | 'src'\n      | 'type'\n      | 'startTime'\n      | 'streamType'\n      | 'autoplay'\n      | 'playbackId'\n      | 'tokens'\n      | 'customDomain'\n    >\n  >,\n  mediaEl: HTMLMediaElement,\n  hls?: Pick<\n    Hls,\n    | 'config'\n    | 'on'\n    | 'once'\n    | 'off'\n    | 'trigger'\n    | 'startLoad'\n    | 'stopLoad'\n    | 'recoverMediaError'\n    | 'destroy'\n    | 'loadSource'\n    | 'attachMedia'\n    | 'liveSyncPosition'\n    | 'subtitleTracks'\n    | 'subtitleTrack'\n    | 'userConfig'\n    | 'audioTrack'\n    | 'audioTracks'\n    | 'autoLevelEnabled'\n    | 'nextLevel'\n    | 'levels'\n    | 'currentLevel'\n  >\n) => {\n  const shouldUseNative = useNative(props, mediaEl);\n  const { src } = props;\n\n  const maybeDispatchEndedCallback = () => {\n    // We want to early bail if the underlying media element is already in an ended state,\n    // since that means it will have already fired the ended event.\n    // Do the \"cheaper\" check first\n    if (mediaEl.ended) return;\n    const pseudoEnded = getEnded(mediaEl, hls);\n    if (!pseudoEnded) return;\n\n    if (isStuckOnLastFragment(mediaEl, hls)) {\n      // Nudge the playhead in this case.\n      mediaEl.currentTime = mediaEl.buffered.end(mediaEl.buffered.length - 1);\n    } else {\n      mediaEl.dispatchEvent(new Event('ended'));\n    }\n  };\n\n  let prevSeekableStart: number | undefined;\n  let prevSeekableEnd: number | undefined;\n\n  const seekableChange = () => {\n    const seekableTimeRanges = getSeekable(mediaEl);\n    let nextSeekableStart: number | undefined;\n    let nextSeekableEnd: number | undefined;\n    if (seekableTimeRanges.length > 0) {\n      nextSeekableStart = seekableTimeRanges.start(0);\n      nextSeekableEnd = seekableTimeRanges.end(0);\n    }\n    if (prevSeekableEnd !== nextSeekableEnd || prevSeekableStart !== nextSeekableStart) {\n      mediaEl.dispatchEvent(new CustomEvent('seekablechange', { composed: true }));\n    }\n    prevSeekableStart = nextSeekableStart;\n    prevSeekableEnd = nextSeekableEnd;\n  };\n\n  // Make sure we track transitions from infinite to finite durations for seekable changes as well.\n  addEventListenerWithTeardown(mediaEl, 'durationchange', seekableChange);\n\n  if (mediaEl && shouldUseNative) {\n    const type = getType(props);\n    if (typeof src === 'string') {\n      // NOTE: This should only be invoked after stream type has been\n      // derived after stream type has been determined.\n      const setupSeekableChangePoll = () => {\n        // Only monitor for seekable updates if StreamType is \"live\" and duration is not finite.\n        if (getStreamType(mediaEl) !== StreamTypes.LIVE || Number.isFinite(mediaEl.duration)) return;\n\n        // Use 1 second since in this context we don't know what the rate of updates\n        // should/will be.\n        // NOTE: We *could* derive the interval rate if we wanted to add logic to our playlist parsing to\n        // account for the per-spec rate of media playlist GETs. See:\n        // https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis-14#section-6.3.4 (CJP)\n        const intervalId = setInterval(seekableChange, 1000);\n\n        // Make sure we clean up after ourselves.\n        mediaEl.addEventListener(\n          'teardown',\n          () => {\n            clearInterval(intervalId);\n          },\n          { once: true }\n        );\n\n        // Assume we're done updating seekable when the duration is finite, which\n        // occurs when e.g. an HLS playlist is ended (`#EXT-X-ENDLIST`).\n        addEventListenerWithTeardown(mediaEl, 'durationchange', () => {\n          if (!Number.isFinite(mediaEl.duration)) return;\n          clearInterval(intervalId);\n        });\n      };\n      const setupNativeStreamInfo = async () => {\n        return updateStreamInfoFromSrc(src, mediaEl, type)\n          .then(setupSeekableChangePoll)\n          .catch((errOrResp: Response | Error) => {\n            if (errOrResp instanceof Response) {\n              const mediaError = getErrorFromResponse(errOrResp, MuxErrorCategory.VIDEO, props);\n              if (mediaError) {\n                mediaEl.dispatchEvent(\n                  new CustomEvent('error', {\n                    detail: mediaError,\n                  })\n                );\n                return;\n              }\n            } else if (errOrResp instanceof Error) {\n              // mediaEl.dispatchEvent(new MediaError())\n            }\n          });\n      };\n      if (mediaEl.preload === 'none') {\n        // NOTE: Previously, we relied on the 'loadstart' event to fetch & parse playlists for stream\n        // info for native playback scenarios. Unfortunately, per spec this event will be dispatched\n        // regardless of the preload state and regardless of whether or not fetching of the src media\n        // has, in fact, begun. In order to respect the provided preferences and avoid eager loading\n        // while still attempting to begin fetching playlists for stream info as early as possible when\n        // media *will* be loaded, we will do a \"first to the finish line\" on both the 'play' event,\n        // which will be dispatched earlier *if* it is the event that initiates media loading, and the\n        // 'loadedmetadata' event, which is dispatched only after the media has finished loading metadata,\n        // but will reliably correlate with media loading. (CJP)\n        // For more, see: Steps 7 & 8 of 'the resource selection algorithm' from \u00A74.8.11.5 Loading the\n        // media resource in the HTML Living Standard\n        // (https://html.spec.whatwg.org/multipage/media.html#concept-media-load-algorithm)\n        const playHandler = () => {\n          setupNativeStreamInfo();\n          mediaEl.removeEventListener('loadedmetadata', loadedMetadataHandler);\n        };\n        const loadedMetadataHandler = () => {\n          setupNativeStreamInfo();\n          mediaEl.removeEventListener('play', playHandler);\n        };\n        addEventListenerWithTeardown(mediaEl, 'play', playHandler, { once: true });\n        addEventListenerWithTeardown(mediaEl, 'loadedmetadata', loadedMetadataHandler, { once: true });\n      } else {\n        setupNativeStreamInfo();\n      }\n\n      // NOTE: Currently use drmToken to signal that playback is expected to be DRM-protected\n      if (props.tokens?.drm) {\n        setupNativeFairplayDRM(props, mediaEl);\n      } else {\n        // If we end up receiving an encrypted event in this case, that means the media is DRM-protected\n        // but a token was not provided.\n        addEventListenerWithTeardown(\n          mediaEl,\n          'encrypted',\n          () => {\n            const message = i18n('Attempting to play DRM-protected content without providing a DRM token.');\n            const mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, true);\n            mediaError.errorCategory = MuxErrorCategory.DRM;\n            mediaError.muxCode = MuxErrorCode.ENCRYPTED_MISSING_TOKEN;\n            mediaEl.dispatchEvent(\n              new CustomEvent('error', {\n                detail: mediaError,\n              })\n            );\n          },\n          { once: true }\n        );\n      }\n\n      mediaEl.setAttribute('src', src);\n      if (props.startTime) {\n        (muxMediaState.get(mediaEl) ?? {}).startTime = props.startTime;\n        // seekable is set to the range of the entire video once durationchange fires\n        mediaEl.addEventListener('durationchange', seekInSeekableRange, { once: true });\n      }\n    } else {\n      mediaEl.removeAttribute('src');\n    }\n\n    mediaEl.addEventListener('error', handleNativeError);\n    mediaEl.addEventListener('error', handleInternalError);\n    mediaEl.addEventListener(\n      'emptied',\n      () => {\n        const trackEls: NodeListOf<HTMLTrackElement> = mediaEl.querySelectorAll('track[data-removeondestroy]');\n        trackEls.forEach((trackEl) => {\n          trackEl.remove();\n        });\n      },\n      { once: true }\n    );\n\n    addEventListenerWithTeardown(mediaEl, 'pause', maybeDispatchEndedCallback);\n    // NOTE: Browsers do not consistently fire an 'ended' event upon seeking to the\n    // end of the media while already paused. This was due to an ambiguity in the\n    // HTML specification, but is now more explicit.\n    // See: https://html.spec.whatwg.org/multipage/media.html#reaches-the-end (CJP)\n    addEventListenerWithTeardown(mediaEl, 'seeked', maybeDispatchEndedCallback);\n\n    addEventListenerWithTeardown(mediaEl, 'play', () => {\n      if (mediaEl.ended) return;\n      if (!isApproximatelyGTE(mediaEl.currentTime, mediaEl.duration)) return;\n      // If we were \"pseudo-ended\" before playback was attempted, seek back to the\n      // beginning to \"replay\", like \"real\" ended behavior.\n      mediaEl.currentTime = mediaEl.seekable.length ? mediaEl.seekable.start(0) : 0;\n    });\n  } else if (hls && src) {\n    hls.once(Hls.Events.LEVEL_LOADED, (_evt, data) => {\n      updateStreamInfoFromHlsjsLevelDetails(data.details, mediaEl, hls);\n      seekableChange();\n      // Only monitor for seekable updates if StreamType is \"live\" and duration is not finite.\n      if (getStreamType(mediaEl) === StreamTypes.LIVE && !Number.isFinite(mediaEl.duration)) {\n        hls.on(Hls.Events.LEVEL_UPDATED, seekableChange);\n\n        // Assume we're done updating seekable when the duration is finite, which\n        // occurs when e.g. an HLS playlist is ended (`#EXT-X-ENDLIST`).\n        addEventListenerWithTeardown(mediaEl, 'durationchange', () => {\n          if (!Number.isFinite(mediaEl.duration)) return;\n          hls.off(Hls.Events.LEVELS_UPDATED, seekableChange);\n        });\n      }\n    });\n\n    hls.on(Hls.Events.ERROR, (_event, data) => {\n      mediaEl.dispatchEvent(\n        new CustomEvent('error', {\n          detail: getErrorFromHlsErrorData(data, props),\n        })\n      );\n    });\n    mediaEl.addEventListener('error', handleInternalError);\n    addEventListenerWithTeardown(mediaEl, 'waiting', maybeDispatchEndedCallback);\n\n    setupMediaTracks(props as HTMLMediaElement, hls);\n    setupTextTracks(mediaEl, hls);\n\n    hls.attachMedia(mediaEl);\n  } else {\n    console.error(\n      \"It looks like the video you're trying to play will not work on this system! If possible, try upgrading to the newest versions of your browser or software.\"\n    );\n  }\n};\n\nfunction seekInSeekableRange(event: Event) {\n  const mediaEl = event.target as HTMLMediaElement;\n  const startTime = muxMediaState.get(mediaEl)?.startTime;\n  if (!startTime) return;\n\n  if (inSeekableRange(mediaEl.seekable, mediaEl.duration, startTime)) {\n    // Setting preload to `none` from `auto` was required on iOS to fix a bug\n    // that caused no `timeupdate` events to fire after seeking \u00AF\\_(\u30C4)_/\u00AF\n    const wasAuto = mediaEl.preload === 'auto';\n    if (wasAuto) {\n      mediaEl.preload = 'none';\n    }\n\n    mediaEl.currentTime = startTime;\n\n    if (wasAuto) {\n      mediaEl.preload = 'auto';\n    }\n  }\n}\n\nasync function handleNativeError(event: Event) {\n  // Return if the event was created or modified by a script or dispatched\n  // via EventTarget.dispatchEvent() preventing an infinite loop.\n  if (!event.isTrusted) return;\n\n  // Stop immediate propagation of the native error event, re-dispatch below!\n  event.stopImmediatePropagation();\n\n  const mediaEl = event.target as HTMLMediaElement;\n  // Safari sometimes throws an error event with a null error.\n  if (!mediaEl?.error) return;\n\n  const { message, code } = mediaEl.error;\n  const error = new MediaError(message, code);\n\n  // This accounts for cases where native playback is being used but\n  // a non-200 response occurs on the request for the playback-id's playlist.\n  // In this case, we currently already fetch the playlist in parallel (for\n  // things like inferring the stream type, live edge start window, etc.),\n  // so we'll wait briefly for that response to translate to a more accurate\n  // error.\n  if (\n    mediaEl.src &&\n    code === MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED &&\n    mediaEl.readyState === HTMLMediaElement.HAVE_NOTHING\n  ) {\n    setTimeout(() => {\n      const ourError = getError(mediaEl) ?? mediaEl.error;\n      // If the code is (still) MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED,\n      // assume it's an (unlikely) case where we did, in fact, encounter\n      // media that is unsupported.\n      if (ourError?.code === MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED) {\n        mediaEl.dispatchEvent(\n          new CustomEvent('error', {\n            detail: error,\n          })\n        );\n      }\n      // Since a parallel request for the source should be initiated to determine\n      // stream info (e.g. streamType) at roughly the same time as when the source\n      // is loaded by the media element, we should be able to keep this timeout short.\n      // NOTE: Although there is a case where the parallel request may happen later\n      // (namely, after metadata is loaded), this should be mutually exclusive from\n      // the case we're accounting for here, since unsupported media should not\n      // ever get metadata loaded in the first place. (CJP)\n    }, 500);\n    return;\n  }\n\n  if (mediaEl.src && (code !== MediaError.MEDIA_ERR_DECODE || code !== undefined)) {\n    // Attempt to get the response code from the video src url.\n    try {\n      const { status } = await fetch(mediaEl.src);\n      // Use the same hls.js data structure.\n      error.data = { response: { code: status } };\n    } catch {}\n  }\n\n  mediaEl.dispatchEvent(\n    new CustomEvent('error', {\n      detail: error,\n    })\n  );\n}\n\n/**\n * Use a event listener instead of a function call when dispatching the Custom error\n * event so consumers are still able to disable or intercept this error event.\n * @param {Event} event\n */\nfunction handleInternalError(event: Event | CustomEvent<MediaError>) {\n  if (!(event instanceof CustomEvent) || !(event.detail instanceof MediaError)) return;\n\n  const mediaEl = event.target as HTMLMediaElement;\n  const error = event.detail;\n  // Prevent tracking non-fatal errors in Mux data.\n  if (!error || !error.fatal) return;\n\n  (muxMediaState.get(mediaEl) ?? {}).error = error as unknown as HTMLMediaElement['error'];\n\n  // Only pass valid mux-embed props: player_error_code, player_error_message, player_error_context\n  mediaEl.mux?.emit('error', {\n    player_error_code: error.code,\n    player_error_message: error.message,\n    player_error_context: error.context,\n  });\n}\n\nconst getErrorFromHlsErrorData = (\n  data: ErrorData,\n  props: Partial<Pick<MuxMediaPropsInternal, 'playbackId' | 'drmToken' | 'playbackToken' | 'tokens'>>\n) => {\n  console.error('getErrorFromHlsErrorData()', data);\n  const ErrorCodeMap: Partial<Record<ValueOf<typeof Hls.ErrorTypes>, 0 | 1 | 2 | 3 | 4 | 5>> = {\n    [Hls.ErrorTypes.NETWORK_ERROR]: MediaError.MEDIA_ERR_NETWORK,\n    [Hls.ErrorTypes.MEDIA_ERROR]: MediaError.MEDIA_ERR_DECODE,\n    [Hls.ErrorTypes.KEY_SYSTEM_ERROR]: MediaError.MEDIA_ERR_ENCRYPTED,\n  } as const;\n\n  // eslint-disable-next-line no-shadow\n  const hlsErrorDataToErrorCode = (data: ErrorData) => {\n    if (\n      [\n        ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED,\n        ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED,\n      ].includes(data.details)\n    ) {\n      return MediaError.MEDIA_ERR_NETWORK;\n    }\n    return ErrorCodeMap[data.type];\n  };\n\n  // eslint-disable-next-line no-shadow\n  const hlsErrorDataToCategory = (data: ErrorData) => {\n    if (data.type === ErrorTypes.KEY_SYSTEM_ERROR) return MuxErrorCategory.DRM;\n    if (data.type === ErrorTypes.NETWORK_ERROR) return MuxErrorCategory.VIDEO;\n  };\n\n  let mediaError: MediaError;\n  const errorCode = hlsErrorDataToErrorCode(data);\n  if (errorCode === MediaError.MEDIA_ERR_NETWORK && data.response) {\n    const category = hlsErrorDataToCategory(data) ?? MuxErrorCategory.VIDEO;\n    mediaError = getErrorFromResponse(data.response, category, props) ?? new MediaError('', errorCode);\n  } else if (errorCode === MediaError.MEDIA_ERR_ENCRYPTED) {\n    if (data.details === ErrorDetails.KEY_SYSTEM_NO_CONFIGURED_LICENSE) {\n      const message = i18n('Attempting to play DRM-protected content without providing a DRM token.');\n      mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, data.fatal);\n      mediaError.errorCategory = MuxErrorCategory.DRM;\n      mediaError.muxCode = MuxErrorCode.ENCRYPTED_MISSING_TOKEN;\n    } else if (data.details === ErrorDetails.KEY_SYSTEM_NO_ACCESS) {\n      /** @TODO For UI message add suggestion to try another browser */\n      const message = i18n(\n        'Cannot play DRM-protected content with current security configuration on this browser. Try playing in another browser.'\n      );\n      // Should we flag this as a business exception?\n      mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, data.fatal);\n      mediaError.errorCategory = MuxErrorCategory.DRM;\n      mediaError.muxCode = MuxErrorCode.ENCRYPTED_UNSUPPORTED_KEY_SYSTEM;\n    } else if (data.details === ErrorDetails.KEY_SYSTEM_NO_SESSION) {\n      const message = i18n(\n        'Failed to generate a DRM license request. This may be an issue with the player or your protected content.'\n      );\n      // NOTE: For some reason, perhaps due to issues with EXT-X-KEY parsing, hls.js defines this as a non-fatal error.\n      // For us, we should be able to assume it is instead fatal. (CJP)\n      mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, true);\n      mediaError.errorCategory = MuxErrorCategory.DRM;\n      mediaError.muxCode = MuxErrorCode.ENCRYPTED_GENERATE_REQUEST_FAILED;\n    } else if (data.details === ErrorDetails.KEY_SYSTEM_SESSION_UPDATE_FAILED) {\n      const message = i18n(\n        'Failed to update DRM license. This may be an issue with the player or your protected content.'\n      );\n      mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, data.fatal);\n      mediaError.errorCategory = MuxErrorCategory.DRM;\n      mediaError.muxCode = MuxErrorCode.ENCRYPTED_UPDATE_LICENSE_FAILED;\n    } else if (data.details === ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_UPDATE_FAILED) {\n      const message = i18n(\n        'Your server certificate failed when attempting to set it. This may be an issue with a no longer valid certificate.'\n      );\n      mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, data.fatal);\n      mediaError.errorCategory = MuxErrorCategory.DRM;\n      mediaError.muxCode = MuxErrorCode.ENCRYPTED_UPDATE_SERVER_CERT_FAILED;\n    } else if (data.details === ErrorDetails.KEY_SYSTEM_STATUS_INTERNAL_ERROR) {\n      const message = i18n(\n        'The DRM Content Decryption Module system had an internal failure. Try reloading the page, upading your browser, or playing in another browser.'\n      );\n      mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, data.fatal);\n      mediaError.errorCategory = MuxErrorCategory.DRM;\n      mediaError.muxCode = MuxErrorCode.ENCRYPTED_CDM_ERROR;\n    } else if (data.details === ErrorDetails.KEY_SYSTEM_STATUS_OUTPUT_RESTRICTED) {\n      const message = i18n(\n        'DRM playback is being attempted in an environment that is not sufficiently secure. User may see black screen.'\n      );\n      // NOTE: When encountered, this is a non-fatal error (though it's certainly interruptive of standard playback experience). (CJP)\n      mediaError = new MediaError(message, MediaError.MEDIA_ERR_ENCRYPTED, false);\n      mediaError.errorCategory = MuxErrorCategory.DRM;\n      mediaError.muxCode = MuxErrorCode.ENCRYPTED_OUTPUT_RESTRICTED;\n    } else {\n      mediaError = new MediaError(data.error.message, MediaError.MEDIA_ERR_ENCRYPTED, data.fatal);\n      mediaError.errorCategory = MuxErrorCategory.DRM;\n      mediaError.muxCode = MuxErrorCode.ENCRYPTED_ERROR;\n    }\n  } else {\n    mediaError = new MediaError('', errorCode, data.fatal);\n  }\n  if (!mediaError.context) {\n    mediaError.context =\n      `${data.url ? `url: ${data.url}\\n` : ''}` +\n      `${\n        data.response && (data.response.code || data.response.text)\n          ? `response: ${data.response.code}, ${data.response.text}\\n`\n          : ''\n      }` +\n      `${data.reason ? `failure reason: ${data.reason}\\n` : ''}` +\n      `${data.level ? `level: ${data.level}\\n` : ''}` +\n      `${data.parent ? `parent stream controller: ${data.parent}\\n` : ''}` +\n      `${data.buffer ? `buffer length: ${data.buffer}\\n` : ''}` +\n      `${data.error ? `error: ${data.error}\\n` : ''}` +\n      `${data.event ? `event: ${data.event}\\n` : ''}` +\n      `${data.err ? `error message: ${data.err?.message}\\n` : ''}`;\n  }\n  mediaError.data = data;\n  return mediaError;\n};\n", "import Hls from 'hls.js';\nimport type HlsClassType from 'hls.js';\nexport default Hls;\nexport type HlsInterface = HlsClassType;\n", "// Identifies what kind of request was made that resulted in an error\nexport const MuxErrorCategory = {\n  VIDEO: 'video',\n  THUMBNAIL: 'thumbnail',\n  STORYBOARD: 'storyboard',\n  DRM: 'drm',\n} as const;\n\nexport const MuxErrorCode = {\n  NOT_AN_ERROR: 0,\n  NETWORK_OFFLINE: 2000002,\n  NETWORK_UNKNOWN_ERROR: 2000000,\n  NETWORK_NO_STATUS: 2000001,\n  NETWORK_INVALID_URL: 2400000,\n  NETWORK_NOT_FOUND: 2404000,\n  NETWORK_NOT_READY: 2412000,\n  NETWORK_GENERIC_SERVER_FAIL: 2500000,\n  NETWORK_TOKEN_MISSING: 2403201,\n  NETWORK_TOKEN_MALFORMED: 2412202,\n  NETWORK_TOKEN_EXPIRED: 2403210,\n  NETWORK_TOKEN_AUD_MISSING: 2403221,\n  NETWORK_TOKEN_AUD_MISMATCH: 2403222,\n  NETWORK_TOKEN_SUB_MISMATCH: 2403232,\n  ENCRYPTED_ERROR: 5000000, // Generic\n  ENCRYPTED_UNSUPPORTED_KEY_SYSTEM: 5000001,\n  ENCRYPTED_GENERATE_REQUEST_FAILED: 5000002,\n  ENCRYPTED_UPDATE_LICENSE_FAILED: 5000003,\n  ENCRYPTED_UPDATE_SERVER_CERT_FAILED: 5000004,\n  ENCRYPTED_CDM_ERROR: 5000005,\n  ENCRYPTED_OUTPUT_RESTRICTED: 5000006,\n  ENCRYPTED_MISSING_TOKEN: 5000002,\n} as const;\n\nexport type MuxErrorCategory = typeof MuxErrorCategory;\nexport type MuxErrorCode = typeof MuxErrorCode;\n\nexport type MuxErrorCategoryValue = MuxErrorCategory[keyof MuxErrorCategory];\nexport type MuxErrorCodeValue = MuxErrorCode[keyof MuxErrorCode];\n\nexport const errorCategoryToTokenNameOrPrefix = (category: MuxErrorCategoryValue) => {\n  if (category === MuxErrorCategory.VIDEO) return 'playback';\n  return category;\n};\n\nexport class MediaError extends Error {\n  static MEDIA_ERR_ABORTED = 1 as const;\n  static MEDIA_ERR_NETWORK = 2 as const;\n  static MEDIA_ERR_DECODE = 3 as const;\n  static MEDIA_ERR_SRC_NOT_SUPPORTED = 4 as const;\n  static MEDIA_ERR_ENCRYPTED = 5 as const;\n  // @see https://docs.mux.com/guides/data/monitor-html5-video-element#customize-error-tracking-behavior\n  static MEDIA_ERR_CUSTOM = 100;\n\n  static defaultMessages: Record<number, string> = {\n    1: 'You aborted the media playback',\n    2: 'A network error caused the media download to fail.',\n    3: 'A media error caused playback to be aborted. The media could be corrupt or your browser does not support this format.',\n    4: 'An unsupported error occurred. The server or network failed, or your browser does not support this format.',\n    5: 'The media is encrypted and there are no keys to decrypt it.',\n  };\n\n  name: string;\n  code: number;\n  public muxCode?: MuxErrorCodeValue;\n  public errorCategory?: MuxErrorCategoryValue;\n  context?: string;\n  fatal: boolean;\n  data?: any;\n\n  constructor(message?: string, code: number = MediaError.MEDIA_ERR_CUSTOM, fatal?: boolean, context?: string) {\n    super(message);\n    this.name = 'MediaError';\n    this.code = code;\n    this.context = context;\n    this.fatal = fatal ?? (code >= MediaError.MEDIA_ERR_NETWORK && code <= MediaError.MEDIA_ERR_ENCRYPTED);\n\n    if (!this.message) {\n      this.message = MediaError.defaultMessages[this.code] ?? '';\n    }\n  }\n}\n", "/* eslint @typescript-eslint/triple-slash-reference: \"off\" */\n/// <reference path=\"../../../node_modules/mux-embed/dist/types/mux-embed.d.ts\" preserve=\"true\" />\nimport type { Options } from 'mux-embed';\nimport type { MediaError } from './errors';\nimport type { HlsConfig } from 'hls.js';\nimport type Hls from 'hls.js';\n\ntype KeyTypes = string | number | symbol;\ntype Maybe<T> = T | null | undefined;\n\nconst isNil = (x: unknown): x is null | undefined => x == undefined;\n\n// Type Guard to determine if a given key is actually a key of some object of type T\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport const isKeyOf = <T extends {} = any>(k: KeyTypes, o: Maybe<T>): k is keyof T => {\n  if (isNil(o)) return false;\n  return k in o;\n};\n\nexport type ValueOf<T> = T[keyof T];\nexport type Metadata = Partial<Required<Options>['data']>;\ntype MetaData = Metadata;\nexport type PlaybackEngine = Hls;\n\nexport type PlaybackCore = {\n  engine?: PlaybackEngine;\n  setAutoplay: (autoplay?: Autoplay) => void;\n  setPreload: (preload?: HTMLMediaElement['preload']) => void;\n};\n\n// TODO add INVIEW_MUTED, INVIEW_ANY\nexport type AutoplayTypes = {\n  ANY: 'any';\n  MUTED: 'muted';\n};\n\nexport const AutoplayTypes: AutoplayTypes = {\n  ANY: 'any',\n  MUTED: 'muted',\n};\n\nexport type Autoplay = boolean | ValueOf<AutoplayTypes>;\n\nexport type HlsPlaylistTypes = 'VOD' | 'EVENT' | null | undefined;\n\nexport type StreamTypes = {\n  ON_DEMAND: 'on-demand';\n  LIVE: 'live';\n  UNKNOWN: 'unknown';\n};\n\nexport const StreamTypes: StreamTypes = {\n  ON_DEMAND: 'on-demand',\n  LIVE: 'live',\n  UNKNOWN: 'unknown',\n};\n\nexport type PlaybackTypes = {\n  MSE: 'mse';\n  NATIVE: 'native';\n};\n\nexport const PlaybackTypes: PlaybackTypes = {\n  MSE: 'mse',\n  NATIVE: 'native',\n};\n\nexport type CmcdTypes = {\n  HEADER: 'header';\n  QUERY: 'query';\n  NONE: 'none';\n};\n\nexport const CmcdTypes: CmcdTypes = {\n  HEADER: 'header',\n  QUERY: 'query',\n  NONE: 'none',\n};\n\nexport const CmcdTypeValues = Object.values(CmcdTypes);\n\nexport type ExtensionMimeTypeMap = {\n  M3U8: 'application/vnd.apple.mpegurl';\n  MP4: 'video/mp4';\n};\n\nexport const ExtensionMimeTypeMap: ExtensionMimeTypeMap = {\n  M3U8: 'application/vnd.apple.mpegurl',\n  MP4: 'video/mp4',\n};\n\nexport type MimeTypeShorthandMap = {\n  HLS: ExtensionMimeTypeMap['M3U8'];\n};\n\nexport const MimeTypeShorthandMap: MimeTypeShorthandMap = {\n  HLS: ExtensionMimeTypeMap.M3U8,\n};\n\nexport const shorthandKeys = Object.keys(MimeTypeShorthandMap);\n\nexport type MediaTypes =\n  | ValueOf<ExtensionMimeTypeMap>\n  | keyof MimeTypeShorthandMap\n  /** @TODO Figure out a way to \"downgrade\" derived types below to early TS syntax (e.g. 3.4) instead of explicit versions here (CJP) */\n  | 'hls';\n// | `${Lowercase<keyof MimeTypeShorthandMap>}`\n// | `${Uppercase<keyof MimeTypeShorthandMap>}`;\n\nexport const allMediaTypes = [\n  ...(Object.values(ExtensionMimeTypeMap) as ValueOf<ExtensionMimeTypeMap>[]),\n  /** @TODO Figure out a way to \"downgrade\" derived types below to early TS syntax (e.g. 3.4) instead of explicit versions here (CJP) */\n  'hls',\n  'HLS',\n  // ...(shorthandKeys as (keyof MimeTypeShorthandMap)[]),\n  // ...(shorthandKeys.map((k) => k.toUpperCase()) as `${Uppercase<keyof MimeTypeShorthandMap>}`[]),\n  // ...(shorthandKeys.map((k) => k.toLowerCase()) as `${Lowercase<keyof MimeTypeShorthandMap>}`[]),\n] as MediaTypes[];\n\n// Both cuepoints and chapters have optional end times\n// so support both joined up and sparse cue placements\ntype CueLike<T = any> = {\n  startTime: number;\n  endTime?: number;\n  value: T;\n};\nexport type CuePoint<T = any> =\n  | CueLike<T> // new shape\n  | { time: number; value: T }; // legacy shape, still supported for now\nexport type Chapter = CueLike<string>;\n\nexport const MaxResolution = {\n  upTo720p: '720p',\n  upTo1080p: '1080p',\n  upTo1440p: '1440p',\n  upTo2160p: '2160p',\n} as const;\n\nexport const MinResolution = {\n  noLessThan480p: '480p',\n  noLessThan540p: '540p',\n  noLessThan720p: '720p',\n  noLessThan1080p: '1080p',\n  noLessThan1440p: '1440p',\n  noLessThan2160p: '2160p',\n} as const;\n\nexport const RenditionOrder = {\n  DESCENDING: 'desc',\n} as const;\n\nexport type MaxResolutionValue = ValueOf<typeof MaxResolution>;\nexport type MinResolutionValue = ValueOf<typeof MinResolution>;\nexport type RenditionOrderValue = ValueOf<typeof RenditionOrder>;\n\nexport type Tokens = {\n  playback?: string;\n  drm?: string;\n  thumbnail?: string;\n  storyboard?: string;\n};\n\nexport type MuxMediaPropTypes = {\n  _hlsConfig?: Partial<HlsConfig>;\n  autoPlay?: Autoplay;\n  autoplay?: Autoplay;\n  beaconCollectionDomain: Options['beaconCollectionDomain'];\n  customDomain: string;\n  debug: Options['debug'] & Hls['config']['debug'];\n  disableCookies: Options['disableCookies'];\n  disableTracking: boolean;\n  drmToken?: string;\n  playbackToken?: string;\n  envKey: MetaData['env_key'];\n  error?: HTMLMediaElement['error'] | MediaError;\n  errorTranslator: Options['errorTranslator'];\n  liveEdgeStart: number;\n  maxResolution: MaxResolutionValue;\n  metadata: Partial<Options['data']>;\n  minResolution: MinResolutionValue;\n  playbackId: string;\n  playerInitTime: MetaData['player_init_time'];\n  preferCmcd: ValueOf<CmcdTypes> | undefined;\n  preferPlayback: ValueOf<PlaybackTypes> | undefined;\n  programStartTime: number;\n  programEndTime: number;\n  assetStartTime: number;\n  assetEndTime: number;\n  renditionOrder: RenditionOrderValue;\n  startTime: Hls['config']['startPosition'];\n  streamType: ValueOf<StreamTypes>;\n  targetLiveWindow: number;\n  tokens: Tokens;\n  type: MediaTypes;\n  extraSourceParams: Record<string, any>;\n};\n\nexport type HTMLMediaElementProps = Partial<Pick<HTMLMediaElement, 'src' | 'preload' | 'error' | 'seekable'>>;\n\nexport type MuxMediaProps = HTMLMediaElementProps & MuxMediaPropTypes;\nexport type MuxMediaPropsInternal = MuxMediaProps & {\n  playerSoftwareName: MetaData['player_software_name'];\n  playerSoftwareVersion: MetaData['player_software_version'];\n  drmTypeCb?: (drmType: Metadata['view_drm_type']) => void;\n};\n", "const code = 'en'; export default { code }", "import { isKeyOf, ExtensionMimeTypeMap, MimeTypeShorthandMap, StreamTypes } from './types';\nimport type { HlsPlaylistTypes, MuxMediaProps } from './types';\n// @ts-ignore\nimport lang from '../lang/en.json';\n\ntype addEventListenerWithTeardown = <\n  K extends keyof HTMLMediaElementEventMap,\n  T extends EventTarget = HTMLMediaElement,\n>(\n  mediaEl: HTMLMediaElement,\n  type: K,\n  listener: (this: T, ev: HTMLMediaElementEventMap[K]) => any,\n  options?: boolean | AddEventListenerOptions,\n  target?: T | HTMLMediaElement\n) => void;\n\n// Adds an event listener to a media element that will be removed when an 'teardown' event is dispatched.\n// Using this instead of 'emptied' as that can fire on initial load based on prior state of the media element\n// Will be fired as a result of (directly or indirectly) invoking playback-core's `teardown()` function.\nexport const addEventListenerWithTeardown: addEventListenerWithTeardown = (\n  mediaEl,\n  type,\n  listener,\n  options,\n  target = mediaEl\n) => {\n  /** @TODO fix types (hard problem due to lack of explicit relationship between Element and EventMap definitions) */\n  // @ts-ignore\n  target.addEventListener(type, listener, options);\n  // NOTE: Using custom teardown\n  mediaEl.addEventListener(\n    'teardown',\n    () => {\n      /** @TODO fix types (hard problem due to lack of explicit relationship between Element and EventMap definitions) */\n      // @ts-ignore\n      target.removeEventListener(type, listener);\n    },\n    { once: true }\n  );\n};\n\nexport function inSeekableRange(seekable: TimeRanges, duration: number, time: number) {\n  if (duration && time > duration) {\n    time = duration;\n  }\n  for (let i = 0; i < seekable.length; i++) {\n    if (seekable.start(i) <= time && seekable.end(i) >= time) {\n      return true;\n    }\n  }\n  return false;\n}\n\nexport const toPlaybackIdParts = (playbackIdWithOptionalParams: string): [string, string?] => {\n  const qIndex = playbackIdWithOptionalParams.indexOf('?');\n  if (qIndex < 0) return [playbackIdWithOptionalParams];\n  const idPart = playbackIdWithOptionalParams.slice(0, qIndex);\n  const queryPart = playbackIdWithOptionalParams.slice(qIndex);\n  return [idPart, queryPart];\n};\n\nexport const getType = (props: Partial<Pick<MuxMediaProps, 'type' | 'src'>>) => {\n  const type = props.type;\n  if (type) {\n    const upperType = type.toUpperCase();\n    return isKeyOf(upperType, MimeTypeShorthandMap) ? MimeTypeShorthandMap[upperType] : type;\n  }\n\n  const { src } = props;\n  if (!src) return '';\n\n  return inferMimeTypeFromURL(src);\n};\n\nexport const toStreamTypeFromPlaylistType = (playlistType: HlsPlaylistTypes) => {\n  return playlistType === 'VOD' ? StreamTypes.ON_DEMAND : StreamTypes.LIVE;\n};\n\nexport const toTargetLiveWindowFromPlaylistType = (playlistType: HlsPlaylistTypes) => {\n  if (playlistType === 'EVENT') return Number.POSITIVE_INFINITY;\n  if (playlistType === 'VOD') return Number.NaN;\n  return 0;\n};\n\nexport const inferMimeTypeFromURL = (url: string) => {\n  let pathname = '';\n  try {\n    pathname = new URL(url).pathname;\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  } catch (_e) {\n    console.error('invalid url');\n  }\n\n  const extDelimIdx = pathname.lastIndexOf('.');\n  if (extDelimIdx < 0) return '';\n\n  const ext = pathname.slice(extDelimIdx + 1);\n  const upperExt = ext.toUpperCase();\n\n  return isKeyOf(upperExt, ExtensionMimeTypeMap) ? ExtensionMimeTypeMap[upperExt] : '';\n};\n\nexport type MuxJWT = {\n  sub: string;\n  aud: 'v' | 't' | 'g' | 's' | 'd';\n  exp: number;\n};\n\nexport const parseJwt = (token: string | undefined): Partial<MuxJWT> | undefined => {\n  const base64Url = (token ?? '').split('.')[1];\n\n  // exit early on invalid value\n  if (!base64Url) return undefined;\n\n  // Account for malformed JWTs\n  try {\n    const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');\n    const jsonPayload = decodeURIComponent(\n      atob(base64)\n        .split('')\n        .map(function (c) {\n          return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);\n        })\n        .join('')\n    );\n    return JSON.parse(jsonPayload);\n  } catch {\n    return undefined;\n  }\n};\n\nexport const isJWTExpired = ({ exp }: Partial<Pick<MuxJWT, 'exp'>>, referenceTime: number = Date.now()) => {\n  return !exp || exp * 1000 < referenceTime;\n};\n\n// NOTE: Treating missing sub (and expected sub) as mismatches for now (CJP)\nexport const isJWTSubMismatch = ({ sub }: Partial<Pick<MuxJWT, 'sub'>>, expectedSub: string | undefined) => {\n  return sub !== expectedSub;\n};\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport const isJWTAudMissing = ({ aud }: Partial<Pick<MuxJWT, 'aud'>>, _expectedAud: string | undefined) => {\n  return !aud;\n};\n\nexport const isJWTAudMismatch = ({ aud }: Partial<Pick<MuxJWT, 'aud'>>, expectedAud: string | undefined) => {\n  return aud !== expectedAud;\n};\n\nconst DEFAULT_LOCALE = 'en';\n\n// NL example\n// lang = {\n//   \"Network Error\": \"Netwerk Fout\",\n// };\nexport function i18n(str: string, translate = true): any {\n  const message = translate ? (lang as unknown as any)?.[str] ?? str : str;\n  const locale = translate ? (lang as unknown as any).code : DEFAULT_LOCALE;\n  return new IntlMessageFormat(message, locale);\n}\n\n/**\n * Poor man's IntlMessageFormat, enrich if need be.\n * @see https://formatjs.io/docs/intl-messageformat/\n */\nclass IntlMessageFormat {\n  message: string;\n  locale: string;\n\n  /** @TODO re-implement esbuild custom plugin for code usage (CJP) */\n  constructor(message: string, locale = (lang as unknown as any) ?? DEFAULT_LOCALE) {\n    this.message = message;\n    this.locale = locale;\n  }\n\n  format(values: Record<string, any>): string {\n    return this.message.replace(/\\{(\\w+)\\}/g, (match, key) => {\n      return values[key] ?? '';\n    });\n  }\n\n  toString() {\n    return this.message;\n  }\n}\n", "import { addEventListenerWithTeardown } from './util';\nimport { ValueOf, Autoplay, AutoplayTypes, PlaybackEngine, MuxMediaPropsInternal, StreamTypes } from './types';\nimport Hls from './hls';\n\nconst AutoplayTypeValues = Object.values(AutoplayTypes);\nexport const isAutoplayValue = (value: unknown): value is Autoplay => {\n  return (\n    typeof value === 'boolean' ||\n    (typeof value === 'string' && AutoplayTypeValues.includes(value as ValueOf<AutoplayTypes>))\n  );\n};\n\n// Given a video element, will listen to lifecycle events to determine important\n// things like whether the video is live or whether the video has played\n// and then handles autoplaying the video as appropraite.\n// It works with both the native video element or hls.js.\n// This returns a method UpdateAutoplay, that allows the user to change\n// the value of the autoplay attribute and it will react appropriately.\nexport const setupAutoplay = (\n  props: Partial<MuxMediaPropsInternal>,\n  mediaEl: HTMLMediaElement,\n  hls?: PlaybackEngine\n) => {\n  const { autoplay: maybeAutoplay } = props;\n  let hasPlayed = false;\n  let isLive = false;\n  let autoplay: Autoplay = isAutoplayValue(maybeAutoplay) ? maybeAutoplay : !!maybeAutoplay;\n\n  const updateHasPlayed = () => {\n    // hasPlayed\n\n    if (!hasPlayed) {\n      addEventListenerWithTeardown(\n        mediaEl,\n        'playing',\n        () => {\n          hasPlayed = true;\n        },\n        { once: true }\n      );\n    }\n  };\n\n  updateHasPlayed();\n\n  // on `loadstart`\n  // hasPlayed should default to false\n  // we should try and autoplay\n  addEventListenerWithTeardown(\n    mediaEl,\n    'loadstart',\n    () => {\n      hasPlayed = false;\n      updateHasPlayed();\n      handleAutoplay(mediaEl, autoplay);\n    },\n    { once: true }\n  );\n\n  // on `loadedmetadata` we can check whether we're live in the case of native playback\n  addEventListenerWithTeardown(\n    mediaEl,\n    'loadstart',\n    () => {\n      // only update isLive here if we're using native playback\n      if (!hls) {\n        // defer to streamType if set (including inferred)\n        if (props.streamType && props.streamType !== StreamTypes.UNKNOWN) {\n          isLive = props.streamType === StreamTypes.LIVE;\n        } else {\n          isLive = !Number.isFinite(mediaEl.duration);\n        }\n      }\n      handleAutoplay(mediaEl, autoplay);\n    },\n    { once: true }\n  );\n\n  // determine if we're live for hls.js\n  if (hls) {\n    hls.once(Hls.Events.LEVEL_LOADED, (e: any, data: any) => {\n      // defer to streamType if set (including inferred)\n      if (props.streamType && props.streamType !== StreamTypes.UNKNOWN) {\n        isLive = props.streamType === StreamTypes.LIVE;\n      } else {\n        isLive = data.details.live ?? false;\n      }\n    });\n  }\n\n  // When we are not auto-playing, we should seek to the live sync position\n  // This will seek first play event of *any* live video including event-type,\n  // which probably shouldn't seek\n  if (!autoplay) {\n    const handleSeek = () => {\n      // don't seek if we're not live or if a `startTime` has been explicitly set\n      if (!isLive || Number.isFinite(props.startTime)) {\n        return;\n      }\n      // seek to either hls.js's liveSyncPosition or the native seekable end\n      if (hls?.liveSyncPosition) {\n        mediaEl.currentTime = hls.liveSyncPosition;\n      } else {\n        if (Number.isFinite(mediaEl.seekable.end(0))) {\n          mediaEl.currentTime = mediaEl.seekable.end(0);\n        }\n      }\n    };\n    if (hls) {\n      addEventListenerWithTeardown(\n        mediaEl,\n        'play',\n        () => {\n          if (mediaEl.preload === 'metadata') {\n            hls.once(Hls.Events.LEVEL_UPDATED, handleSeek);\n          } else {\n            handleSeek();\n          }\n        },\n        { once: true }\n      );\n    }\n  }\n\n  // this method allows us to update the value of autoplay\n  // and try autoplaying appropriately.\n  const updateAutoplay = (newAutoplay?: Autoplay) => {\n    if (!hasPlayed) {\n      autoplay = isAutoplayValue(newAutoplay) ? newAutoplay : !!newAutoplay;\n      handleAutoplay(mediaEl, autoplay);\n    }\n  };\n\n  return updateAutoplay;\n};\n\nexport const handleAutoplay = (mediaEl: HTMLMediaElement, autoplay: Autoplay) => {\n  if (!autoplay) {\n    return;\n  }\n\n  const oldMuted = mediaEl.muted;\n  const restoreMuted = () => (mediaEl.muted = oldMuted);\n\n  switch (autoplay) {\n    // ANY:\n    // try to play with current options\n    // if it fails, mute and try playing again\n    // if that fails, restore muted state and don't try playing again\n    case AutoplayTypes.ANY:\n      mediaEl.play().catch(() => {\n        mediaEl.muted = true;\n        mediaEl.play().catch(restoreMuted);\n      });\n      break;\n\n    // MUTED:\n    // mute the player and then try playing\n    // if that fails, restore muted state\n    case AutoplayTypes.MUTED:\n      mediaEl.muted = true;\n      mediaEl.play().catch(restoreMuted);\n      break;\n\n    // Default or if autoplay is a boolean attribute:\n    // Try playing the video and catch the failed autoplay warning\n    default: // eslint-disable-next-line\n      mediaEl.play().catch(() => {});\n      break;\n  }\n};\n", "import { addEventListenerWithTeardown } from './util';\nimport { PlaybackEngine } from './types';\n\nexport const setupPreload = (\n  { preload, src }: Partial<HTMLMediaElement>,\n  mediaEl: HTMLMediaElement,\n  hls?: PlaybackEngine\n) => {\n  const updatePreload = (val?: HTMLMediaElement['preload']) => {\n    if (val != null && ['', 'none', 'metadata', 'auto'].includes(val)) {\n      mediaEl.setAttribute('preload', val);\n    } else {\n      mediaEl.removeAttribute('preload');\n    }\n  };\n\n  // handle native without hls.js (MSE)\n  if (!hls) {\n    updatePreload(preload);\n    return updatePreload;\n  }\n\n  let hasLoadedSource = false;\n  let hasPlayFired = false;\n\n  const originalLength = hls.config.maxBufferLength;\n  const originalSize = hls.config.maxBufferSize;\n\n  const updateHlsPreload = (val?: HTMLMediaElement['preload']) => {\n    // even if it doesn't have an effect on a <video> w/ MSE\n    // still update the `preload` attribute.\n    updatePreload(val);\n\n    const newPreload = val ?? mediaEl.preload;\n    if (hasPlayFired || newPreload === 'none') return;\n    if (newPreload === 'metadata') {\n      // load the least amount of data possible\n      hls.config.maxBufferLength = 1;\n      hls.config.maxBufferSize = 1;\n    } else {\n      hls.config.maxBufferLength = originalLength;\n      hls.config.maxBufferSize = originalSize;\n    }\n\n    safeLoadSource();\n  };\n\n  const safeLoadSource = () => {\n    if (!hasLoadedSource && src) {\n      hasLoadedSource = true;\n      hls.loadSource(src);\n    }\n  };\n\n  addEventListenerWithTeardown(\n    mediaEl,\n    'play',\n    () => {\n      hasPlayFired = true;\n\n      // once a user has played, allow for it to load data as normal\n      hls.config.maxBufferLength = originalLength;\n      hls.config.maxBufferSize = originalSize;\n\n      // load the source on first play if needed\n      safeLoadSource();\n    },\n    { once: true }\n  );\n\n  updateHlsPreload(preload);\n\n  return updateHlsPreload;\n};\n", "import Hls from './hls';\n\nexport function setupMediaTracks(\n  customMediaEl: HTMLMediaElement,\n  hls: Pick<\n    Hls,\n    'audioTrack' | 'audioTracks' | 'autoLevelEnabled' | 'nextLevel' | 'levels' | 'on' | 'once' | 'off' | 'trigger'\n  >\n) {\n  if (!('videoTracks' in customMediaEl)) return;\n\n  // Create a map to save the unique id's we create for each level and rendition.\n  // hls.js uses the levels array index primarily but we'll use the id to have a\n  // 1 to 1 relation from rendition to level.\n  const levelIdMap = new WeakMap();\n\n  hls.on(Hls.Events.MANIFEST_PARSED, function (event, data) {\n    removeAllMediaTracks();\n\n    const videoTrack = customMediaEl.addVideoTrack('main');\n    videoTrack.selected = true;\n\n    for (const [id, level] of data.levels.entries()) {\n      const videoRendition = videoTrack.addRendition(\n        level.url[0],\n        level.width,\n        level.height,\n        level.videoCodec,\n        level.bitrate\n      );\n\n      // The returned levels all have an id of `0`, save the id in a WeakMap.\n      levelIdMap.set(level, `${id}`);\n      videoRendition.id = `${id}`;\n    }\n  });\n\n  hls.on(Hls.Events.AUDIO_TRACKS_UPDATED, function (event, data) {\n    removeAudioTracks();\n\n    for (const a of data.audioTracks) {\n      // hls.js doesn't return a `kind` property for audio tracks yet.\n      const kind = a.default ? 'main' : 'alternative';\n      const audioTrack = customMediaEl.addAudioTrack(kind, a.name, a.lang);\n      audioTrack.id = `${a.id}`;\n\n      if (a.default) {\n        audioTrack.enabled = true;\n      }\n    }\n  });\n\n  customMediaEl.audioTracks.addEventListener('change', () => {\n    // Cast to number, hls.js uses numeric id's.\n    const audioTrackId = +[...customMediaEl.audioTracks].find((t) => t.enabled)?.id;\n    const availableIds = hls.audioTracks.map((t) => t.id);\n    if (audioTrackId != hls.audioTrack && availableIds.includes(audioTrackId)) {\n      hls.audioTrack = audioTrackId;\n    }\n  });\n\n  // Fired when a level is removed after calling `removeLevel()`\n  hls.on(Hls.Events.LEVELS_UPDATED, function (event, data) {\n    const videoTrack = customMediaEl.videoTracks[customMediaEl.videoTracks.selectedIndex ?? 0];\n    if (!videoTrack) return;\n\n    const levelIds: string[] = data.levels.map((l) => levelIdMap.get(l));\n\n    for (const rendition of customMediaEl.videoRenditions) {\n      if (rendition.id && !levelIds.includes(rendition.id)) {\n        videoTrack.removeRendition(rendition);\n      }\n    }\n  });\n\n  // hls.js doesn't support enabling multiple renditions.\n  //\n  // 1. if all renditions are enabled it's auto selection.\n  // 2. if 1 of the renditions is disabled we assume a selection was made\n  //    and lock it to the first rendition that is enabled.\n  const switchRendition = (event: Event) => {\n    // @ts-ignore\n    const level = event.target.selectedIndex as number;\n    if (level != hls.nextLevel) {\n      smoothSwitch(level);\n    }\n  };\n\n  // Workaround for issue changing renditions on an alternative audio track.\n  // https://github.com/video-dev/hls.js/issues/5749#issuecomment-1684629437\n  const smoothSwitch = (levelIndex: number) => {\n    const currentTime = customMediaEl.currentTime;\n    let flushedFwdBuffer = false;\n\n    const callback = (event: string, data: { endOffset: number }) => {\n      flushedFwdBuffer ||= !Number.isFinite(data.endOffset);\n    };\n\n    hls.on(Hls.Events.BUFFER_FLUSHING, callback);\n    hls.nextLevel = levelIndex;\n    hls.off(Hls.Events.BUFFER_FLUSHING, callback);\n\n    if (!flushedFwdBuffer) {\n      hls.trigger(Hls.Events.BUFFER_FLUSHING, {\n        startOffset: currentTime + 10,\n        endOffset: Infinity,\n        type: 'video',\n      });\n    }\n  };\n\n  customMediaEl.videoRenditions?.addEventListener('change', switchRendition);\n\n  const removeVideoTracks = () => {\n    for (const videoTrack of customMediaEl.videoTracks) {\n      customMediaEl.removeVideoTrack(videoTrack);\n    }\n  };\n\n  const removeAudioTracks = () => {\n    for (const audioTrack of customMediaEl.audioTracks) {\n      customMediaEl.removeAudioTrack(audioTrack);\n    }\n  };\n\n  const removeAllMediaTracks = () => {\n    removeVideoTracks();\n    removeAudioTracks();\n  };\n\n  // NOTE: Since this is only relevant for hls, using destroying event (CJP).\n  hls.once(Hls.Events.DESTROYING, removeAllMediaTracks);\n}\n", "import Hls from './hls';\nimport { CuePoint, Chapter } from './types';\nimport { addEventListenerWithTeardown } from './util';\n\ntype Config = { label: string };\n\n// Shared utils\n\n// Extracts the start time from a cuepoint, considering legacy \"time\" prop\nconst cuePointStart = (cuePoint: CuePoint): number => {\n  if ('time' in cuePoint) {\n    return cuePoint.time;\n  }\n  return cuePoint.startTime;\n};\n\nexport function setupTextTracks(\n  mediaEl: HTMLMediaElement,\n  hls: Pick<Hls, 'on' | 'once' | 'subtitleTracks' | 'subtitleTrack'>\n) {\n  hls.on(Hls.Events.NON_NATIVE_TEXT_TRACKS_FOUND, (_type, { tracks }) => {\n    tracks.forEach((trackObj) => {\n      const baseTrackObj = trackObj.subtitleTrack ?? trackObj.closedCaptions;\n      const idx = hls.subtitleTracks.findIndex(({ lang, name, type }) => {\n        return lang == baseTrackObj?.lang && name === trackObj.label && type.toLowerCase() === trackObj.kind;\n      });\n\n      // NOTE: Undocumented method for determining identifier by hls.js. Relied on for\n      // ensuring CUES_PARSED events can identify and apply cues to the appropriate track (CJP).\n      // See: https://github.com/video-dev/hls.js/blob/master/src/controller/timeline-controller.ts#L640\n      const id = trackObj._id ?? trackObj.default ? 'default' : `${trackObj.kind}${idx}`;\n\n      addTextTrack(mediaEl, trackObj.kind as TextTrackKind, trackObj.label, baseTrackObj?.lang, id, trackObj.default);\n    });\n  });\n\n  const changeHandler = () => {\n    if (!hls.subtitleTracks.length) return;\n\n    const showingTrack = Array.from(mediaEl.textTracks).find((textTrack) => {\n      return textTrack.id && textTrack.mode === 'showing' && ['subtitles', 'captions'].includes(textTrack.kind);\n    });\n\n    if (!showingTrack) return;\n\n    const currentHlsTrack = hls.subtitleTracks[hls.subtitleTrack];\n\n    // If hls.subtitleTrack is -1 or its id changed compared to the one that is showing load the new subtitle track.\n    const hlsTrackId = !currentHlsTrack\n      ? undefined\n      : currentHlsTrack.default\n        ? 'default'\n        : `${hls.subtitleTracks[hls.subtitleTrack].type.toLowerCase()}${hls.subtitleTrack}`;\n\n    if (hls.subtitleTrack < 0 || showingTrack?.id !== hlsTrackId) {\n      const idx = hls.subtitleTracks.findIndex(({ lang, name, type, default: defaultTrack }) => {\n        return (\n          (showingTrack.id === 'default' && defaultTrack) ||\n          (lang == showingTrack.language && name === showingTrack.label && type.toLowerCase() === showingTrack.kind)\n        );\n      });\n      // After the subtitleTrack is set here, hls.js will load the playlist and CUES_PARSED events will be fired below.\n      hls.subtitleTrack = idx;\n    }\n\n    if (showingTrack?.id === hlsTrackId) {\n      // Refresh the cues after a texttrack mode change to fix a Chrome bug causing the captions not to render.\n      if (showingTrack.cues) {\n        Array.from(showingTrack.cues).forEach((cue) => {\n          showingTrack.addCue(cue);\n        });\n      }\n    }\n  };\n\n  mediaEl.textTracks.addEventListener('change', changeHandler);\n\n  hls.on(Hls.Events.CUES_PARSED, (_type, { track, cues }) => {\n    const textTrack = mediaEl.textTracks.getTrackById(track);\n    if (!textTrack) return;\n\n    const disabled = textTrack.mode === 'disabled';\n    if (disabled) {\n      textTrack.mode = 'hidden';\n    }\n\n    cues.forEach((cue: VTTCue) => {\n      if (textTrack.cues?.getCueById(cue.id)) return;\n      textTrack.addCue(cue);\n    });\n\n    if (disabled) {\n      textTrack.mode = 'disabled';\n    }\n  });\n\n  // NOTE: Since this is only relevant for hls, using destroying event (CJP).\n  hls.once(Hls.Events.DESTROYING, () => {\n    mediaEl.textTracks.removeEventListener('change', changeHandler);\n    // Use data attribute to identify tracks that should be removed when switching sources/destroying hls.js instance.\n    const trackEls: NodeListOf<HTMLTrackElement> = mediaEl.querySelectorAll('track[data-removeondestroy]');\n    trackEls.forEach((trackEl) => {\n      trackEl.remove();\n    });\n  });\n\n  const forceHiddenTracks = () => {\n    // Keeping this a forEach in case we want to expand the scope of this.\n    Array.from(mediaEl.textTracks).forEach((track) => {\n      if (['subtitles', 'caption'].includes(track.kind)) return;\n      if (!(track.label === 'thumbnails' || track.kind === 'chapters')) return;\n      if (!track.cues?.length) {\n        let selector = 'track';\n        if (track.kind) selector += `[kind=\"${track.kind}\"]`;\n        if (track.label) selector += `[label=\"${track.label}\"]`;\n        const trackEl = mediaEl.querySelector(selector);\n        // Force a reload of the cues if they've been removed\n        const src = trackEl?.getAttribute('src') ?? '';\n        trackEl?.removeAttribute('src');\n        setTimeout(() => {\n          trackEl?.setAttribute('src', src);\n        }, 0);\n      }\n      // Force hidden mode if it's not hidden\n      if (track.mode !== 'hidden') {\n        track.mode = 'hidden';\n      }\n    });\n  };\n\n  // hls.js will forcibly clear all cues from tracks on manifest loads or media attaches.\n  // This ensures that we re-load them after it's done that.\n  hls.once(Hls.Events.MANIFEST_LOADED, forceHiddenTracks);\n  hls.once(Hls.Events.MEDIA_ATTACHED, forceHiddenTracks);\n}\n\nexport function addTextTrack(\n  mediaEl: HTMLMediaElement,\n  kind: TextTrackKind,\n  label: string,\n  lang?: string,\n  id?: string,\n  defaultTrack?: boolean\n): TextTrack {\n  const trackEl = document.createElement('track');\n  trackEl.kind = kind;\n  trackEl.label = label;\n  if (lang) {\n    // This attribute must be present if the element's kind attribute is in the subtitles state.\n    trackEl.srclang = lang;\n  }\n  if (id) {\n    trackEl.id = id;\n  }\n  if (!!defaultTrack) {\n    trackEl.default = true;\n  }\n  trackEl.track.mode = ['subtitles', 'captions'].includes(kind) ? 'disabled' : 'hidden';\n\n  // Add data attribute to identify tracks that should be removed when switching sources/destroying hls.js instance.\n  trackEl.setAttribute('data-removeondestroy', '');\n  mediaEl.append(trackEl);\n\n  return trackEl.track as TextTrack;\n}\n\nexport function removeTextTrack(mediaEl: HTMLMediaElement, track: TextTrack) {\n  const trackElement: HTMLTrackElement | undefined = Array.prototype.find.call(\n    mediaEl.querySelectorAll('track'),\n    (trackEl: HTMLTrackElement) => trackEl.track === track\n  );\n  trackElement?.remove();\n}\n\nexport function getTextTrack(mediaEl: HTMLMediaElement, label: string, kind: TextTrackKind) {\n  return Array.from(mediaEl.querySelectorAll('track')).find((trackEl) => {\n    return trackEl.track.label === label && trackEl.track.kind === kind;\n  })?.track;\n}\n\nexport async function addCuesToTextTrack<T = any>(\n  mediaEl: HTMLMediaElement,\n  cues: CuePoint<T>[] | Chapter[],\n  label: string,\n  kind: TextTrackKind\n) {\n  // If the track has already been created/added, use it.\n  let track = getTextTrack(mediaEl, label, kind);\n  if (!track) {\n    // Otherwise, create a new one\n    track = addTextTrack(mediaEl, kind, label);\n    track.mode = 'hidden';\n    // Wait a tick before providing a newly created track. Otherwise e.g. cues disappear when using track.addCue().\n    await new Promise((resolve) => setTimeout(() => resolve(undefined), 0));\n  }\n\n  if (track.mode !== 'hidden') {\n    track.mode = 'hidden';\n  }\n\n  // Copy cuePoints to ensure sort is not mutative\n  [...cues]\n    // Sort descending to ensure last cuepoints are added as cues first. This is done\n    // so the track's cue's can be used for reference when determining an appropriate\n    // endTime, allowing support of multiple invocations of addCuePoints\n    .sort((cuePointA, cuePointB) => cuePointStart(cuePointB) - cuePointStart(cuePointA))\n    .forEach((cuePoint) => {\n      const value = cuePoint.value;\n      const startTime = cuePointStart(cuePoint);\n\n      if ('endTime' in cuePoint && cuePoint.endTime != undefined) {\n        track?.addCue(\n          new VTTCue(\n            startTime,\n            cuePoint.endTime,\n            kind === 'chapters' ? (value as string) : JSON.stringify(value ?? null)\n          )\n        );\n      } else {\n        // find the cue that starts immediately after the cuePoint's time\n        const cueAfterIndex = Array.prototype.findIndex.call(track?.cues, (cue) => cue.startTime >= startTime);\n        const cueAfter = track?.cues?.[cueAfterIndex];\n        const endTime = cueAfter\n          ? cueAfter.startTime\n          : Number.isFinite(mediaEl.duration)\n            ? mediaEl.duration\n            : Number.MAX_SAFE_INTEGER;\n\n        // Adjust the endTime of the already added previous cue,\n        // if present, so it does not overlap with the newly added cue.\n        const previousCue = track?.cues?.[cueAfterIndex - 1];\n        if (previousCue) {\n          previousCue.endTime = startTime;\n        }\n        track?.addCue(\n          new VTTCue(startTime, endTime, kind === 'chapters' ? (value as string) : JSON.stringify(value ?? null))\n        );\n      }\n    });\n\n  // NOTE: this doesn't naturally fire when we update the list\n  // of cue points (without changing the active cue). We manually\n  // fire this to force the state manager to reflect the new change\n  mediaEl.textTracks.dispatchEvent(\n    new Event('change', {\n      bubbles: true,\n      composed: true,\n    })\n  );\n\n  return track;\n}\n\n// Cuepoints\n\nconst DEFAULT_CUEPOINTS_TRACK_LABEL = 'cuepoints';\nexport const DefaultCuePointsConfig: Config = Object.freeze({ label: DEFAULT_CUEPOINTS_TRACK_LABEL });\n\nexport async function addCuePoints<T>(\n  mediaEl: HTMLMediaElement,\n  cuePoints: CuePoint<T>[],\n  cuePointsConfig: Config = DefaultCuePointsConfig\n) {\n  return addCuesToTextTrack(mediaEl, cuePoints, cuePointsConfig.label, 'metadata');\n}\n\nconst toCuePoint = (cue: VTTCue) => ({\n  time: cue.startTime,\n  value: JSON.parse(cue.text),\n});\n\nexport function getCuePoints(\n  mediaEl: HTMLMediaElement,\n  cuePointsConfig: Config = { label: DEFAULT_CUEPOINTS_TRACK_LABEL }\n) {\n  const track = getTextTrack(mediaEl, cuePointsConfig.label, 'metadata');\n  if (!track?.cues) return [];\n  return Array.from(track.cues, (cue) => toCuePoint(cue as VTTCue));\n}\n\nexport function getActiveCuePoint(\n  mediaEl: HTMLMediaElement,\n  cuePointsConfig: Config = { label: DEFAULT_CUEPOINTS_TRACK_LABEL }\n) {\n  const track = getTextTrack(mediaEl, cuePointsConfig.label, 'metadata');\n  if (!track?.activeCues?.length) return undefined;\n  if (track.activeCues.length === 1) return toCuePoint(track.activeCues[0] as VTTCue);\n  // NOTE: There is a bug in Chromium where there may be \"lingering activeCues\" even\n  // after the playhead is no longer within their [startTime, endTime) bounds. This\n  // accounts for those cases (CJP)\n  const { currentTime } = mediaEl;\n  const actualActiveCue = Array.prototype.find.call(track.activeCues ?? [], ({ startTime, endTime }) => {\n    return startTime <= currentTime && endTime > currentTime;\n  }) as VTTCue | undefined;\n  if (!actualActiveCue) {\n    return toCuePoint(track.activeCues[0] as VTTCue);\n  }\n  return toCuePoint(actualActiveCue);\n}\n\nexport async function setupCuePoints(mediaEl: HTMLMediaElement, cuePointsConfig: Config = DefaultCuePointsConfig) {\n  return new Promise((resolve) => {\n    addEventListenerWithTeardown(mediaEl, 'loadstart', async () => {\n      const track = await addCuePoints(mediaEl, [], cuePointsConfig);\n      addEventListenerWithTeardown(\n        mediaEl,\n        'cuechange',\n        () => {\n          const activeCuePoint = getActiveCuePoint(mediaEl);\n          if (activeCuePoint) {\n            const evt = new CustomEvent('cuepointchange', {\n              composed: true,\n              bubbles: true,\n              detail: activeCuePoint,\n            });\n            mediaEl.dispatchEvent(evt);\n          }\n        },\n        {},\n        track\n      );\n      resolve(track);\n    });\n  });\n}\n\n/**\n * Chapters\n */\n\nconst DEFAULT_CHAPTERS_TRACK_LABEL = 'chapters';\nexport const DefaultChaptersConfig: Config = Object.freeze({ label: DEFAULT_CHAPTERS_TRACK_LABEL });\n\nconst vttCueToChapter = (cue: VTTCue) => ({\n  startTime: cue.startTime,\n  endTime: cue.endTime,\n  value: cue.text,\n});\n\nexport async function addChapters(\n  mediaEl: HTMLMediaElement,\n  chapters: Chapter[],\n  chaptersConfig: Config = DefaultChaptersConfig\n) {\n  return addCuesToTextTrack(mediaEl, chapters, chaptersConfig.label, 'chapters');\n}\n\nexport function getChapters(\n  mediaEl: HTMLMediaElement,\n  chaptersConfig: Config = { label: DEFAULT_CHAPTERS_TRACK_LABEL }\n) {\n  const track = getTextTrack(mediaEl, chaptersConfig.label, 'chapters');\n  if (!track?.cues?.length) return [];\n  return Array.from(track.cues, (cue) => vttCueToChapter(cue as VTTCue));\n}\n\nexport function getActiveChapter(\n  mediaEl: HTMLMediaElement,\n  chaptersConfig: Config = { label: DEFAULT_CHAPTERS_TRACK_LABEL }\n) {\n  const track = getTextTrack(mediaEl, chaptersConfig.label, 'chapters');\n  if (!track?.activeCues?.length) return undefined;\n  if (track.activeCues.length === 1) return vttCueToChapter(track.activeCues[0] as VTTCue);\n  // NOTE: There is a bug in Chromium where there may be \"lingering activeCues\" even\n  // after the playhead is no longer within their [startTime, endTime) bounds. This\n  // accounts for those cases (CJP)\n  const { currentTime } = mediaEl;\n  const actualActiveCue = Array.prototype.find.call(track.activeCues ?? [], ({ startTime, endTime }) => {\n    return startTime <= currentTime && endTime > currentTime;\n  }) as VTTCue | undefined;\n  if (!actualActiveCue) {\n    return vttCueToChapter(track.activeCues[0] as VTTCue);\n  }\n  return vttCueToChapter(actualActiveCue);\n}\n\nexport async function setupChapters(mediaEl: HTMLMediaElement, chaptersConfig: Config = DefaultChaptersConfig) {\n  return new Promise((resolve) => {\n    addEventListenerWithTeardown(mediaEl, 'loadstart', async () => {\n      const track = await addChapters(mediaEl, [], chaptersConfig);\n\n      addEventListenerWithTeardown(\n        mediaEl,\n        'cuechange',\n        () => {\n          const activeCuePoint = getActiveChapter(mediaEl);\n          if (activeCuePoint) {\n            const evt = new CustomEvent('chapterchange', {\n              composed: true,\n              bubbles: true,\n              detail: activeCuePoint,\n            });\n            mediaEl.dispatchEvent(evt);\n          }\n        },\n        {},\n        track\n      );\n\n      resolve(track);\n    });\n  });\n}\n", "import { PlaybackEngine } from './types';\n\ntype MediaWithPDT = HTMLMediaElement & { getStartDate?: () => Date };\n\nexport function getStartDate(mediaEl: MediaWithPDT, hls: PlaybackEngine | undefined) {\n  if (hls) {\n    const playingDate = hls.playingDate;\n\n    if (playingDate != null) {\n      // If the video is very long and the currentTime will transition day boundaries,\n      // this may end up not being accurate\n      return new Date(playingDate.getTime() - mediaEl.currentTime * 1000);\n    }\n  }\n\n  if (typeof mediaEl.getStartDate === 'function') {\n    return mediaEl.getStartDate();\n  }\n\n  return new Date(NaN);\n}\n\nexport function getCurrentPdt(mediaEl: MediaWithPDT, hls: PlaybackEngine | undefined) {\n  if (hls && hls.playingDate) {\n    return hls.playingDate;\n  }\n\n  if (typeof mediaEl.getStartDate === 'function') {\n    const startDate = mediaEl.getStartDate();\n\n    // If the video is very long and the currentTime will transition day boundaries,\n    // this may end up not being accurate\n    return new Date(startDate.getTime() + mediaEl.currentTime * 1000);\n  }\n\n  return new Date(NaN);\n}\n", "import type { LoaderResponse } from 'hls.js';\nimport {\n  i18n,\n  isJWTAudMismatch,\n  isJWTAudMissing,\n  isJWTExpired,\n  isJWTSubMismatch,\n  parseJwt,\n  toPlaybackIdParts,\n} from './util';\nimport { isKeyOf, MuxMediaPropsInternal } from './types';\nimport type { MuxErrorCategoryValue } from './errors';\nimport { errorCategoryToTokenNameOrPrefix, MediaError, MuxErrorCategory, MuxErrorCode } from './errors';\n\nexport const MuxJWTAud = {\n  VIDEO: 'v',\n  // NOTE: These are not \"built in\" for mux-video/mux-audio (only mux-player) (CJP)\n  THUMBNAIL: 't',\n  STORYBOARD: 's',\n  // GIF: 'g', // currently unused\n  DRM: 'd',\n} as const;\n\nexport const categoryToAud = (category: MuxErrorCategoryValue) => {\n  if (category === MuxErrorCategory.VIDEO) return MuxJWTAud.VIDEO;\n  if (category === MuxErrorCategory.DRM) return MuxJWTAud.DRM;\n};\n\nexport const categoryToToken = (\n  category: MuxErrorCategoryValue,\n  muxMediaEl: Partial<Pick<MuxMediaPropsInternal, 'drmToken' | 'playbackToken' | 'tokens'>>\n) => {\n  const nameOrPrefix = errorCategoryToTokenNameOrPrefix(category);\n  const tokenName = `${nameOrPrefix}Token` as const;\n  if (muxMediaEl.tokens?.[nameOrPrefix]) return muxMediaEl.tokens?.[nameOrPrefix];\n  return isKeyOf(tokenName, muxMediaEl) ? muxMediaEl[tokenName] : undefined;\n};\n\nexport const getErrorFromResponse = (\n  resp: Pick<Response, 'status' | 'url'> | Pick<LoaderResponse, 'code' | 'url'>,\n  category: MuxErrorCategoryValue,\n  muxMediaEl: Partial<Pick<MuxMediaPropsInternal, 'playbackId' | 'drmToken' | 'playbackToken' | 'tokens'>>,\n  translate = false,\n  offline = !globalThis.navigator?.onLine // NOTE: Passing this in for testing purposes\n) => {\n  if (offline) {\n    const message = i18n(`Your device appears to be offline`, translate);\n    const context = undefined;\n    const mediaErrorCode = MediaError.MEDIA_ERR_NETWORK;\n    const mediaError = new MediaError(message, mediaErrorCode, true, context);\n    mediaError.errorCategory = category;\n    mediaError.muxCode = MuxErrorCode.NETWORK_OFFLINE;\n    mediaError.data = resp;\n    return mediaError;\n  }\n  const status = 'status' in resp ? resp.status : resp.code;\n  const requestTime = Date.now();\n  const mediaErrorCode = MediaError.MEDIA_ERR_NETWORK;\n  // Not an error. WHAT ARE YOU EVEN DOING HERE?!?\n  if (status === 200) return undefined;\n  const tokenNamePrefix = errorCategoryToTokenNameOrPrefix(category);\n  const token = categoryToToken(category, muxMediaEl);\n  const expectedAud = categoryToAud(category);\n  const [playbackId] = toPlaybackIdParts(muxMediaEl.playbackId ?? '');\n  // NOTE: *should* have playback id when reaching here\n  // if (!status) return MuxErrorCode.NETWORK_NO_STATUS;\n  if (!status || !playbackId) return undefined;\n\n  const jwtObj = parseJwt(token);\n  // Make sure we didn't get here because of a malformed JWT and/or claim\n  if (!!token && !jwtObj) {\n    // 403 for DRM\n    const message = i18n(`The {tokenNamePrefix}-token provided is invalid or malformed.`, translate).format({\n      tokenNamePrefix,\n    });\n    const context = i18n(`Compact JWT string: {token}`, translate).format({\n      token,\n    });\n    const mediaError = new MediaError(message, mediaErrorCode, true, context);\n    mediaError.errorCategory = category;\n    mediaError.muxCode = MuxErrorCode.NETWORK_TOKEN_MALFORMED;\n    mediaError.data = resp;\n    return mediaError;\n  }\n\n  if (status >= 500) {\n    /**\n     * @TODO We plausibly should have some basic retry logic for all other 500 status\n     * cases (CJP)\n     **/\n    const mediaError = new MediaError('', mediaErrorCode, true);\n    mediaError.errorCategory = category;\n    mediaError.muxCode = MuxErrorCode.NETWORK_UNKNOWN_ERROR;\n    /** @TODO Add error msg + context crud here (NOT YET DEFINED) (CJP) */\n    return mediaError;\n  }\n\n  if (status === 403) {\n    if (jwtObj) {\n      if (isJWTExpired(jwtObj, requestTime)) {\n        const dateOptions: any = {\n          timeStyle: 'medium',\n          dateStyle: 'medium',\n        };\n        // E.g. for DRM: \"The video\u2019s secured drm-token has expired.\"\n        // E.g. for Video: \"The video\u2019s secured playback-token has expired.\"\n        const message = i18n(`The video\u2019s secured {tokenNamePrefix}-token has expired.`, translate).format({\n          tokenNamePrefix,\n        });\n        const context = i18n(`Expired at: {expiredDate}. Current time: {currentDate}.`, translate).format({\n          expiredDate: new Intl.DateTimeFormat('en', dateOptions).format(jwtObj.exp ?? 0 * 1000),\n          currentDate: new Intl.DateTimeFormat('en', dateOptions).format(requestTime),\n        });\n        const mediaError = new MediaError(message, mediaErrorCode, true, context);\n        mediaError.errorCategory = category;\n        mediaError.muxCode = MuxErrorCode.NETWORK_TOKEN_EXPIRED;\n        mediaError.data = resp;\n        return mediaError;\n      }\n      if (isJWTSubMismatch(jwtObj, playbackId)) {\n        const message = i18n(\n          `The video\u2019s playback ID does not match the one encoded in the {tokenNamePrefix}-token.`,\n          translate\n        ).format({\n          tokenNamePrefix,\n        });\n        const context = i18n(\n          `Specified playback ID: {playbackId} and the playback ID encoded in the {tokenNamePrefix}-token: {tokenPlaybackId}`,\n          translate\n        ).format({\n          tokenNamePrefix,\n          playbackId,\n          tokenPlaybackId: jwtObj.sub,\n        });\n        const mediaError = new MediaError(message, mediaErrorCode, true, context);\n        mediaError.errorCategory = category;\n        mediaError.muxCode = MuxErrorCode.NETWORK_TOKEN_SUB_MISMATCH;\n        mediaError.data = resp;\n        return mediaError;\n      }\n      if (isJWTAudMissing(jwtObj, expectedAud)) {\n        const message = i18n(`The {tokenNamePrefix}-token is formatted with incorrect information.`, translate).format({\n          tokenNamePrefix,\n        });\n        const context = i18n(\n          `The {tokenNamePrefix}-token has no aud value. aud value should be {expectedAud}.`,\n          translate\n        ).format({\n          tokenNamePrefix,\n          expectedAud,\n        });\n        const mediaError = new MediaError(message, mediaErrorCode, true, context);\n        mediaError.errorCategory = category;\n        mediaError.muxCode = MuxErrorCode.NETWORK_TOKEN_AUD_MISSING;\n        mediaError.data = resp;\n        return mediaError;\n      }\n      if (isJWTAudMismatch(jwtObj, expectedAud)) {\n        const message = i18n(`The {tokenNamePrefix}-token is formatted with incorrect information.`, translate).format({\n          tokenNamePrefix,\n        });\n        const context = i18n(\n          `The {tokenNamePrefix}-token has an incorrect aud value: {aud}. aud value should be {expectedAud}.`,\n          translate\n        ).format({\n          tokenNamePrefix,\n          expectedAud,\n          aud: jwtObj.aud,\n        });\n        const mediaError = new MediaError(message, mediaErrorCode, true, context);\n        mediaError.errorCategory = category;\n        mediaError.muxCode = MuxErrorCode.NETWORK_TOKEN_AUD_MISMATCH;\n        mediaError.data = resp;\n        return mediaError;\n      }\n\n      // NOTE: This *should* not happen for DRM, since the drm token\n      // is currently used to detect whether or not DRM should\n      // be setup at all. Including for exhaustiveness. (CJP)\n    } else {\n      const message = i18n(\n        `Authorization error trying to access this {category} URL. If this is a signed URL, you might need to provide a {tokenNamePrefix}-token.`,\n        translate\n      ).format({\n        tokenNamePrefix,\n        category,\n      });\n      const context = i18n(`Specified playback ID: {playbackId}`, translate).format({ playbackId });\n      const mediaError = new MediaError(message, mediaErrorCode, true, context);\n      mediaError.errorCategory = category;\n      mediaError.muxCode = MuxErrorCode.NETWORK_TOKEN_MISSING;\n      mediaError.data = resp;\n      return mediaError;\n    }\n  }\n\n  if (status === 412) {\n    const message = i18n(\n      `This playback-id may belong to a live stream that is not currently active or an asset that is not ready.`,\n      translate\n    );\n    const context = i18n(`Specified playback ID: {playbackId}`, translate).format({ playbackId });\n    const mediaError = new MediaError(message, mediaErrorCode, true, context);\n    mediaError.errorCategory = category;\n    mediaError.muxCode = MuxErrorCode.NETWORK_NOT_READY;\n    mediaError.data = resp;\n    return mediaError;\n  }\n\n  /**\n   * NOTE: When using a \"structurally valid but non-existent\" playback id for a DRM (license or app certificate) request, this will result in a 403 status.\n   * However, since we will only currently make a DRM request after successfully loading the media, this case should not need\n   * to be accounted for. If we ever eagerly fetch FPS app certs prior to or in parallel to media requests, we would potentially\n   * want to account for that case (either by normalizing statuses, in our messaging for generic 403 above, or through more complex\n   * solutions like waiting for the media response). (CJP)\n   */\n  if (status === 404) {\n    // NOTE: This *should* not happen for DRM (only playback/media requests), since the URL should never be invalid if code\n    // is correct. Aka if we end up here it's almost definitely a bug.\n    const message = i18n(\n      `This URL or playback-id does not exist. You may have used an Asset ID or an ID from a different resource.`,\n      translate\n    );\n    const context = i18n(`Specified playback ID: {playbackId}`, translate).format({ playbackId });\n    const mediaError = new MediaError(message, mediaErrorCode, true, context);\n    mediaError.errorCategory = category;\n    mediaError.muxCode = MuxErrorCode.NETWORK_NOT_FOUND;\n    mediaError.data = resp;\n    return mediaError;\n  }\n\n  /**\n   * NOTE: Omitting a token for a DRM (license or app certificate) request results in a 400 status, unlike playback/media requests,\n   * which are a 403 status (See above).\n   * However, since we will only currently setup Mux Player for DRM if a drm token is provided, this case should not need\n   * to be accounted for. If we ever change this, we would potentially\n   * want to account for that case (either by normalizing statuses, in our messaging for generic 400 above, or through more complex\n   * solutions like checking the category before deciding on error details here). (CJP)\n   */\n  if (status === 400) {\n    const message = i18n(`The URL or playback-id was invalid. You may have used an invalid value as a playback-id.`);\n    const context = i18n(`Specified playback ID: {playbackId}`, translate).format({ playbackId });\n    const mediaError = new MediaError(message, mediaErrorCode, true, context);\n    mediaError.errorCategory = category;\n    mediaError.muxCode = MuxErrorCode.NETWORK_INVALID_URL;\n    mediaError.data = resp;\n    return mediaError;\n  }\n\n  const mediaError = new MediaError('', mediaErrorCode, true);\n  mediaError.errorCategory = category;\n  mediaError.muxCode = MuxErrorCode.NETWORK_UNKNOWN_ERROR;\n  mediaError.data = resp;\n  return mediaError;\n};\n", "/* eslint @typescript-eslint/no-empty-function: \"off\", @typescript-eslint/no-unused-vars: \"off\" */\n\nclass EventTarget {\n  addEventListener() {}\n  removeEventListener() {}\n  dispatchEvent(_event: Event) {\n    return true;\n  }\n}\n\n// @github/template-parts requires DocumentFragment to be available on globalThis for SSR\nif (typeof DocumentFragment === 'undefined') {\n  class DocumentFragment extends EventTarget {}\n  // @ts-ignore\n  globalThis.DocumentFragment = DocumentFragment;\n}\n\nclass HTMLElement extends EventTarget {}\nclass HTMLVideoElement extends EventTarget {}\n\nconst customElements: CustomElementRegistry = {\n  get(_name: string) {\n    return undefined;\n  },\n  define(_name, _constructor, _options) {},\n  getName(_constructor) {\n    return null;\n  },\n  upgrade(_root) {},\n  whenDefined(_name) {\n    return Promise.resolve(HTMLElement as unknown as CustomElementConstructor);\n  },\n};\n\nclass CustomEvent {\n  #detail;\n  get detail() {\n    return this.#detail;\n  }\n  constructor(typeArg: string, eventInitDict: CustomEventInit = {}) {\n    // super(typeArg, eventInitDict);\n    this.#detail = eventInitDict?.detail;\n  }\n  initCustomEvent() {}\n}\n\nfunction createElement(_tagName: string, _options?: ElementCreationOptions): HTMLElement {\n  return new HTMLElement();\n}\n\nconst globalThisShim = {\n  document: {\n    createElement,\n  },\n  DocumentFragment,\n  customElements,\n  CustomEvent,\n  EventTarget,\n  HTMLElement,\n  HTMLVideoElement,\n};\n\n// const isServer = typeof window === 'undefined' || typeof globalThis.customElements === 'undefined';\n// const GlobalThis = isServer ? globalThisShim : globalThis;\n// const Document = isServer ? globalThisShim.document : globalThis.document;\n//\n// export { GlobalThis as globalThis, Document as document };\nconst isServer = typeof window === 'undefined' || typeof globalThis.customElements === 'undefined';\ntype GlobalThis = typeof globalThis;\nconst internalGlobalThis: GlobalThis = (isServer ? globalThisShim : globalThis) as GlobalThis;\nconst internalDocument: Document = (isServer ? globalThisShim.document : globalThis.document) as Document;\n\nexport { internalGlobalThis as globalThis, internalDocument as document };\n", "import { globalThis } from './polyfills';\nimport {\n  initialize,\n  teardown,\n  generatePlayerInitTime,\n  MuxMediaProps,\n  StreamTypes,\n  PlaybackTypes,\n  toMuxVideoURL,\n  Metadata,\n  MediaError,\n  getError,\n  CmcdTypes,\n  CmcdTypeValues,\n  addCuePoints,\n  getCuePoints,\n  getActiveCuePoint,\n  addChapters,\n  getActiveChapter,\n  getStartDate,\n  getCurrentPdt,\n  getStreamType,\n  getTargetLiveWindow,\n  getLiveEdgeStart,\n  getSeekable,\n  getEnded,\n  getChapters,\n  toPlaybackIdFromSrc,\n  toPlaybackIdParts,\n  // isMuxVideoSrc,\n} from '@mux/playback-core';\nimport type {\n  PlaybackCore,\n  PlaybackEngine,\n  Autoplay,\n  ExtensionMimeTypeMap,\n  ValueOf,\n  MaxResolutionValue,\n  MinResolutionValue,\n  RenditionOrderValue,\n  Chapter,\n  CuePoint,\n  Tokens,\n} from '@mux/playback-core';\nimport { getPlayerVersion } from './env';\n// this must be imported after playback-core for the polyfill to be included\nimport { CustomVideoElement, Events as VideoEvents } from 'custom-media-element';\nimport { CastableMediaMixin } from 'castable-video/castable-mixin.js';\nimport { MediaTracksMixin } from 'media-tracks';\nimport type { HlsConfig } from 'hls.js';\n\n// Must mutate so the added events are available in custom-media-element.\nVideoEvents.push('castchange', 'entercast', 'leavecast');\n\nexport const Attributes = {\n  BEACON_COLLECTION_DOMAIN: 'beacon-collection-domain',\n  CUSTOM_DOMAIN: 'custom-domain',\n  DEBUG: 'debug',\n  DISABLE_TRACKING: 'disable-tracking',\n  DISABLE_COOKIES: 'disable-cookies',\n  DRM_TOKEN: 'drm-token',\n  PLAYBACK_TOKEN: 'playback-token',\n  ENV_KEY: 'env-key',\n  MAX_RESOLUTION: 'max-resolution',\n  MIN_RESOLUTION: 'min-resolution',\n  RENDITION_ORDER: 'rendition-order',\n  PROGRAM_START_TIME: 'program-start-time',\n  PROGRAM_END_TIME: 'program-end-time',\n  ASSET_START_TIME: 'asset-start-time',\n  ASSET_END_TIME: 'asset-end-time',\n  METADATA_URL: 'metadata-url',\n  PLAYBACK_ID: 'playback-id',\n  PLAYER_SOFTWARE_NAME: 'player-software-name',\n  PLAYER_SOFTWARE_VERSION: 'player-software-version',\n  PREFER_CMCD: 'prefer-cmcd',\n  PREFER_PLAYBACK: 'prefer-playback',\n  START_TIME: 'start-time',\n  STREAM_TYPE: 'stream-type',\n  TARGET_LIVE_WINDOW: 'target-live-window',\n  LIVE_EDGE_OFFSET: 'live-edge-offset',\n  TYPE: 'type',\n} as const;\n\nconst AttributeNameValues = Object.values(Attributes);\n\nconst playerSoftwareVersion = getPlayerVersion();\nconst playerSoftwareName = 'mux-video';\n\nclass MuxVideoBaseElement extends CustomVideoElement implements Partial<MuxMediaProps> {\n  static get observedAttributes() {\n    return [...AttributeNameValues, ...(CustomVideoElement.observedAttributes ?? [])];\n  }\n\n  #core?: PlaybackCore;\n  #loadRequested?: Promise<void> | null;\n  #playerInitTime: number;\n  #metadata: Readonly<Metadata> = {};\n  #tokens: Tokens = {};\n  #_hlsConfig?: Partial<HlsConfig>;\n  #playerSoftwareVersion?: string;\n  #playerSoftwareName?: string;\n  #errorTranslator?: (errorEvent: any) => any;\n\n  constructor() {\n    super();\n    this.#playerInitTime = generatePlayerInitTime();\n  }\n\n  get preferCmcd() {\n    return (this.getAttribute(Attributes.PREFER_CMCD) as ValueOf<CmcdTypes>) ?? undefined;\n  }\n\n  set preferCmcd(value: ValueOf<CmcdTypes> | undefined) {\n    if (value === this.preferCmcd) return;\n    if (!value) {\n      this.removeAttribute(Attributes.PREFER_CMCD);\n    } else if (CmcdTypeValues.includes(value)) {\n      this.setAttribute(Attributes.PREFER_CMCD, value);\n    } else {\n      console.warn(`Invalid value for preferCmcd. Must be one of ${CmcdTypeValues.join()}`);\n    }\n  }\n\n  get playerInitTime() {\n    return this.#playerInitTime;\n  }\n\n  get playerSoftwareName() {\n    return this.#playerSoftwareName ?? playerSoftwareName;\n  }\n\n  set playerSoftwareName(value: string | undefined) {\n    this.#playerSoftwareName = value;\n  }\n\n  get playerSoftwareVersion() {\n    return this.#playerSoftwareVersion ?? playerSoftwareVersion;\n  }\n\n  set playerSoftwareVersion(value: string | undefined) {\n    this.#playerSoftwareVersion = value;\n  }\n\n  // Keeping this named \"_hls\" since it's exposed for unadvertised \"advanced usage\" via getter that assumes specifically hls.js (CJP)\n  get _hls(): PlaybackEngine | undefined {\n    return this.#core?.engine;\n  }\n\n  get mux(): Readonly<HTMLVideoElement['mux']> | undefined {\n    return this.nativeEl?.mux;\n  }\n\n  get error() {\n    return getError(this.nativeEl) ?? null;\n  }\n\n  get errorTranslator(): ((errorEvent: any) => any) | undefined {\n    return this.#errorTranslator;\n  }\n\n  set errorTranslator(value: ((errorEvent: any) => any) | undefined) {\n    this.#errorTranslator = value;\n  }\n\n  get src() {\n    // Use the attribute value as the source of truth.\n    // No need to store it in two places.\n    // This avoids needing a to read the attribute initially and update the src.\n    return this.getAttribute('src') as string;\n  }\n\n  set src(val: string) {\n    // If being set by attributeChangedCallback,\n    // dont' cause an infinite loop\n    if (val === this.src) return;\n\n    if (val == null) {\n      this.removeAttribute('src');\n    } else {\n      this.setAttribute('src', val);\n    }\n  }\n\n  get type(): ValueOf<ExtensionMimeTypeMap> | undefined {\n    return (this.getAttribute(Attributes.TYPE) as ValueOf<ExtensionMimeTypeMap>) ?? undefined;\n  }\n\n  set type(val: ValueOf<ExtensionMimeTypeMap> | undefined) {\n    // dont' cause an infinite loop\n    if (val === this.type) return;\n\n    if (val) {\n      this.setAttribute(Attributes.TYPE, val);\n    } else {\n      this.removeAttribute(Attributes.TYPE);\n    }\n  }\n\n  /** @ts-ignore */\n  get autoplay(): Autoplay {\n    const attr = this.getAttribute('autoplay');\n\n    if (attr === null) {\n      return false;\n    } else if (attr === '') {\n      return true;\n    } else {\n      return attr as Autoplay;\n    }\n  }\n\n  /** @ts-ignore */\n  set autoplay(val: Autoplay) {\n    const currentVal = this.autoplay;\n    if (val === currentVal) {\n      return;\n    }\n\n    if (val) {\n      this.setAttribute('autoplay', typeof val === 'string' ? val : '');\n    } else {\n      this.removeAttribute('autoplay');\n    }\n  }\n\n  get preload() {\n    const val = this.getAttribute('preload') as HTMLMediaElement['preload'];\n    if (val === '') return 'auto';\n    if (['none', 'metadata', 'auto'].includes(val)) return val;\n    return super.preload;\n  }\n\n  set preload(val) {\n    // don't cause an infinite loop\n    // check the attribute because an empty string maps to the `auto` prop\n    if (val == this.getAttribute('preload')) return;\n\n    if (['', 'none', 'metadata', 'auto'].includes(val)) {\n      this.setAttribute('preload', val);\n    } else {\n      this.removeAttribute('preload');\n    }\n  }\n\n  get debug() {\n    return this.getAttribute(Attributes.DEBUG) != null;\n  }\n\n  set debug(val) {\n    // dont' cause an infinite loop\n    if (val === this.debug) return;\n\n    if (val) {\n      this.setAttribute(Attributes.DEBUG, '');\n    } else {\n      this.removeAttribute(Attributes.DEBUG);\n    }\n  }\n\n  get disableTracking() {\n    return this.hasAttribute(Attributes.DISABLE_TRACKING);\n  }\n\n  set disableTracking(val) {\n    // dont' cause an infinite loop\n    if (val === this.disableTracking) return;\n\n    this.toggleAttribute(Attributes.DISABLE_TRACKING, !!val);\n  }\n\n  get disableCookies() {\n    return this.hasAttribute(Attributes.DISABLE_COOKIES);\n  }\n\n  set disableCookies(val) {\n    // dont' cause an infinite loop\n    if (val === this.disableCookies) return;\n\n    if (val) {\n      this.setAttribute(Attributes.DISABLE_COOKIES, '');\n    } else {\n      this.removeAttribute(Attributes.DISABLE_COOKIES);\n    }\n  }\n\n  get startTime(): number | undefined {\n    const val = this.getAttribute(Attributes.START_TIME);\n    if (val == null) return undefined;\n    const num = +val;\n    return !Number.isNaN(num) ? num : undefined;\n  }\n\n  set startTime(val: number | undefined) {\n    // dont' cause an infinite loop\n    if (val === this.startTime) return;\n\n    if (val == null) {\n      this.removeAttribute(Attributes.START_TIME);\n    } else {\n      this.setAttribute(Attributes.START_TIME, `${val}`);\n    }\n  }\n\n  // NOTE: playbackId may contain additional query params (e.g. token= for playback token) (CJP)\n  get playbackId(): string | undefined {\n    if (this.hasAttribute(Attributes.PLAYBACK_ID)) {\n      return this.getAttribute(Attributes.PLAYBACK_ID) as string;\n    }\n\n    return toPlaybackIdFromSrc(this.src) ?? undefined;\n  }\n\n  set playbackId(val: string | undefined) {\n    // dont' cause an infinite loop\n    if (val === this.playbackId) return;\n\n    if (val) {\n      this.setAttribute(Attributes.PLAYBACK_ID, val);\n    } else {\n      this.removeAttribute(Attributes.PLAYBACK_ID);\n    }\n  }\n\n  get maxResolution() {\n    return (this.getAttribute(Attributes.MAX_RESOLUTION) as MaxResolutionValue) ?? undefined;\n  }\n\n  set maxResolution(val: MaxResolutionValue | undefined) {\n    if (val === this.maxResolution) return;\n\n    if (val) {\n      this.setAttribute(Attributes.MAX_RESOLUTION, val);\n    } else {\n      this.removeAttribute(Attributes.MAX_RESOLUTION);\n    }\n  }\n\n  get minResolution() {\n    return (this.getAttribute(Attributes.MIN_RESOLUTION) as MinResolutionValue) ?? undefined;\n  }\n\n  set minResolution(val: MinResolutionValue | undefined) {\n    if (val === this.minResolution) return;\n\n    if (val) {\n      this.setAttribute(Attributes.MIN_RESOLUTION, val);\n    } else {\n      this.removeAttribute(Attributes.MIN_RESOLUTION);\n    }\n  }\n\n  get renditionOrder() {\n    return (this.getAttribute(Attributes.RENDITION_ORDER) as RenditionOrderValue) ?? undefined;\n  }\n\n  set renditionOrder(val: RenditionOrderValue | undefined) {\n    if (val === this.renditionOrder) return;\n\n    if (val) {\n      this.setAttribute(Attributes.RENDITION_ORDER, val);\n    } else {\n      this.removeAttribute(Attributes.RENDITION_ORDER);\n    }\n  }\n\n  get programStartTime() {\n    const val = this.getAttribute(Attributes.PROGRAM_START_TIME);\n    if (val == null) return undefined;\n    const num = +val;\n    return !Number.isNaN(num) ? num : undefined;\n  }\n\n  set programStartTime(val: number | undefined) {\n    if (val == undefined) {\n      this.removeAttribute(Attributes.PROGRAM_START_TIME);\n    } else {\n      this.setAttribute(Attributes.PROGRAM_START_TIME, `${val}`);\n    }\n  }\n\n  get programEndTime() {\n    const val = this.getAttribute(Attributes.PROGRAM_END_TIME);\n    if (val == null) return undefined;\n    const num = +val;\n    return !Number.isNaN(num) ? num : undefined;\n  }\n\n  set programEndTime(val: number | undefined) {\n    if (val == undefined) {\n      this.removeAttribute(Attributes.PROGRAM_END_TIME);\n    } else {\n      this.setAttribute(Attributes.PROGRAM_END_TIME, `${val}`);\n    }\n  }\n\n  get assetStartTime() {\n    const val = this.getAttribute(Attributes.ASSET_START_TIME);\n    if (val == null) return undefined;\n    const num = +val;\n    return !Number.isNaN(num) ? num : undefined;\n  }\n\n  set assetStartTime(val: number | undefined) {\n    if (val == undefined) {\n      this.removeAttribute(Attributes.ASSET_START_TIME);\n    } else {\n      this.setAttribute(Attributes.ASSET_START_TIME, `${val}`);\n    }\n  }\n\n  get assetEndTime() {\n    const val = this.getAttribute(Attributes.ASSET_END_TIME);\n    if (val == null) return undefined;\n    const num = +val;\n    return !Number.isNaN(num) ? num : undefined;\n  }\n\n  set assetEndTime(val: number | undefined) {\n    if (val == undefined) {\n      this.removeAttribute(Attributes.ASSET_END_TIME);\n    } else {\n      this.setAttribute(Attributes.ASSET_END_TIME, `${val}`);\n    }\n  }\n\n  get customDomain() {\n    return this.getAttribute(Attributes.CUSTOM_DOMAIN) ?? undefined;\n  }\n\n  set customDomain(val: string | undefined) {\n    // dont' cause an infinite loop\n    if (val === this.customDomain) return;\n\n    if (val) {\n      this.setAttribute(Attributes.CUSTOM_DOMAIN, val);\n    } else {\n      this.removeAttribute(Attributes.CUSTOM_DOMAIN);\n    }\n  }\n\n  get drmToken() {\n    return this.getAttribute(Attributes.DRM_TOKEN) ?? undefined;\n  }\n\n  set drmToken(val: string | undefined) {\n    // dont' cause an infinite loop\n    if (val === this.drmToken) return;\n\n    if (val) {\n      this.setAttribute(Attributes.DRM_TOKEN, val);\n    } else {\n      this.removeAttribute(Attributes.DRM_TOKEN);\n    }\n  }\n\n  /**\n   * Get the playback token for signing the src URL.\n   */\n  get playbackToken() {\n    if (this.hasAttribute(Attributes.PLAYBACK_TOKEN)) {\n      return this.getAttribute(Attributes.PLAYBACK_TOKEN) ?? undefined;\n    }\n    if (this.hasAttribute(Attributes.PLAYBACK_ID)) {\n      const [, queryParts] = toPlaybackIdParts(this.playbackId ?? '');\n      return new URLSearchParams(queryParts).get('token') ?? undefined;\n    }\n    if (this.src) {\n      return new URLSearchParams(this.src).get('token') ?? undefined;\n    }\n    return undefined;\n  }\n\n  /**\n   * Set the playback token for signing the src URL.\n   */\n  set playbackToken(val: string | undefined) {\n    if (val === this.playbackToken) return;\n\n    if (val) {\n      this.setAttribute(Attributes.PLAYBACK_TOKEN, val);\n    } else {\n      this.removeAttribute(Attributes.PLAYBACK_TOKEN);\n    }\n  }\n\n  get tokens() {\n    const playback = this.getAttribute(Attributes.PLAYBACK_TOKEN);\n    const drm = this.getAttribute(Attributes.DRM_TOKEN);\n    return {\n      ...this.#tokens,\n      ...(playback != null ? { playback } : {}),\n      ...(drm != null ? { drm } : {}),\n    };\n  }\n\n  set tokens(val) {\n    this.#tokens = val ?? {};\n  }\n\n  get ended() {\n    // This ensures that edge case media that doesn't properly end will\n    // still announce itself as \"ended\".\n    return getEnded(this.nativeEl, this._hls);\n  }\n\n  get envKey(): string | undefined {\n    return this.getAttribute(Attributes.ENV_KEY) ?? undefined;\n  }\n\n  set envKey(val: string | undefined) {\n    // dont' cause an infinite loop\n    if (val === this.envKey) return;\n\n    if (val) {\n      this.setAttribute(Attributes.ENV_KEY, val);\n    } else {\n      this.removeAttribute(Attributes.ENV_KEY);\n    }\n  }\n\n  get beaconCollectionDomain(): string | undefined {\n    return this.getAttribute(Attributes.BEACON_COLLECTION_DOMAIN) ?? undefined;\n  }\n\n  set beaconCollectionDomain(val: string | undefined) {\n    // don't cause an infinite loop\n    if (val === this.beaconCollectionDomain) return;\n\n    if (val) {\n      this.setAttribute(Attributes.BEACON_COLLECTION_DOMAIN, val);\n    } else {\n      this.removeAttribute(Attributes.BEACON_COLLECTION_DOMAIN);\n    }\n  }\n\n  get streamType(): ValueOf<StreamTypes> | undefined {\n    // Allow overriding inferred `streamType`\n    return (this.getAttribute(Attributes.STREAM_TYPE) as ValueOf<StreamTypes>) ?? getStreamType(this.nativeEl);\n  }\n\n  set streamType(val: ValueOf<StreamTypes> | undefined) {\n    // don't cause an infinite loop and avoid change event dispatching\n    if (val === this.streamType) return;\n\n    if (val) {\n      this.setAttribute(Attributes.STREAM_TYPE, val);\n    } else {\n      this.removeAttribute(Attributes.STREAM_TYPE);\n    }\n  }\n\n  get targetLiveWindow() {\n    // Allow overriding inferred `targetLiveWindow`\n    if (this.hasAttribute(Attributes.TARGET_LIVE_WINDOW)) {\n      return +(this.getAttribute(Attributes.TARGET_LIVE_WINDOW) as string) as number;\n    }\n    return getTargetLiveWindow(this.nativeEl);\n  }\n\n  set targetLiveWindow(val: number | undefined) {\n    // don't cause an infinite loop and avoid change event dispatching\n    if (val == this.targetLiveWindow) return;\n\n    if (val == null) {\n      this.removeAttribute(Attributes.TARGET_LIVE_WINDOW);\n    } else {\n      this.setAttribute(Attributes.TARGET_LIVE_WINDOW, `${+val}`);\n    }\n  }\n\n  get liveEdgeStart() {\n    if (this.hasAttribute(Attributes.LIVE_EDGE_OFFSET)) {\n      const { liveEdgeOffset } = this;\n      const seekableEnd = this.nativeEl.seekable.end(0) ?? 0;\n      const seekableStart = this.nativeEl.seekable.start(0) ?? 0;\n      return Math.max(seekableStart, seekableEnd - (liveEdgeOffset as number));\n    }\n    return getLiveEdgeStart(this.nativeEl);\n  }\n\n  get liveEdgeOffset() {\n    if (!this.hasAttribute(Attributes.LIVE_EDGE_OFFSET)) return undefined;\n    return +(this.getAttribute(Attributes.LIVE_EDGE_OFFSET) as string) as number;\n  }\n\n  set liveEdgeOffset(val: number | undefined) {\n    // don't cause an infinite loop and avoid change event dispatching\n    if (val == this.targetLiveWindow) return;\n\n    if (val == null) {\n      this.removeAttribute(Attributes.LIVE_EDGE_OFFSET);\n    } else {\n      this.setAttribute(Attributes.LIVE_EDGE_OFFSET, `${+val}`);\n    }\n  }\n\n  get seekable() {\n    return getSeekable(this.nativeEl);\n  }\n\n  async addCuePoints<T = any>(cuePoints: CuePoint<T>[]) {\n    return addCuePoints(this.nativeEl, cuePoints);\n  }\n\n  get activeCuePoint() {\n    return getActiveCuePoint(this.nativeEl);\n  }\n\n  get cuePoints() {\n    return getCuePoints(this.nativeEl);\n  }\n\n  async addChapters(chapters: Chapter[]) {\n    return addChapters(this.nativeEl, chapters);\n  }\n\n  get activeChapter() {\n    return getActiveChapter(this.nativeEl);\n  }\n\n  get chapters() {\n    return getChapters(this.nativeEl);\n  }\n\n  getStartDate() {\n    return getStartDate(this.nativeEl, this._hls);\n  }\n\n  get currentPdt() {\n    return getCurrentPdt(this.nativeEl, this._hls);\n  }\n\n  get preferPlayback(): ValueOf<PlaybackTypes> | undefined {\n    const val = this.getAttribute(Attributes.PREFER_PLAYBACK);\n    if (val === PlaybackTypes.MSE || val === PlaybackTypes.NATIVE) return val;\n    return undefined;\n  }\n\n  set preferPlayback(val: ValueOf<PlaybackTypes> | undefined) {\n    if (val === this.preferPlayback) return;\n\n    if (val === PlaybackTypes.MSE || val === PlaybackTypes.NATIVE) {\n      this.setAttribute(Attributes.PREFER_PLAYBACK, val);\n    } else {\n      this.removeAttribute(Attributes.PREFER_PLAYBACK);\n    }\n  }\n\n  get metadata() {\n    const inferredMetadataAttrs: { [key: string]: string } = this.getAttributeNames()\n      .filter((attrName) => {\n        return attrName.startsWith('metadata-') && !([Attributes.METADATA_URL] as string[]).includes(attrName);\n      })\n      .reduce(\n        (currAttrs, attrName) => {\n          const value = this.getAttribute(attrName);\n          if (value != null) {\n            currAttrs[attrName.replace(/^metadata-/, '').replace(/-/g, '_') as string] = value;\n          }\n          return currAttrs;\n        },\n        {} as { [key: string]: string }\n      );\n\n    return {\n      ...inferredMetadataAttrs,\n      ...this.#metadata,\n    };\n  }\n\n  set metadata(val: Readonly<Metadata> | undefined) {\n    this.#metadata = val ?? {};\n    if (!!this.mux) {\n      this.mux.emit('hb', this.#metadata);\n    }\n  }\n\n  get _hlsConfig() {\n    return this.#_hlsConfig;\n  }\n\n  set _hlsConfig(val: Readonly<Partial<HlsConfig>> | undefined) {\n    this.#_hlsConfig = val;\n  }\n\n  async #requestLoad() {\n    if (this.#loadRequested) return;\n    await (this.#loadRequested = Promise.resolve());\n    this.#loadRequested = null;\n    this.load();\n  }\n\n  load() {\n    this.#core = initialize(this as Partial<MuxMediaProps>, this.nativeEl, this.#core);\n  }\n\n  unload() {\n    teardown(this.nativeEl, this.#core);\n    this.#core = undefined;\n  }\n\n  attributeChangedCallback(attrName: string, oldValue: string | null, newValue: string | null) {\n    // Only forward the attributes to the native media element that are not handled.\n    const isNativeAttr = CustomVideoElement.observedAttributes.includes(attrName);\n    if (isNativeAttr && !['src', 'autoplay', 'preload'].includes(attrName)) {\n      super.attributeChangedCallback(attrName, oldValue, newValue);\n    }\n\n    switch (attrName) {\n      case Attributes.PLAYER_SOFTWARE_NAME:\n        this.playerSoftwareName = newValue ?? undefined;\n        break;\n      case Attributes.PLAYER_SOFTWARE_VERSION:\n        this.playerSoftwareVersion = newValue ?? undefined;\n        break;\n      case 'src': {\n        const hadSrc = !!oldValue;\n        const hasSrc = !!newValue;\n        if (!hadSrc && hasSrc) {\n          this.#requestLoad();\n        } else if (hadSrc && !hasSrc) {\n          this.unload();\n        } else if (hadSrc && hasSrc) {\n          this.unload();\n          this.#requestLoad();\n        }\n        break;\n      }\n      case 'autoplay':\n        if (newValue === oldValue) {\n          break;\n        }\n        /** In case newValue is an empty string or null, use this.autoplay which translates to booleans (WL) */\n        this.#core?.setAutoplay(this.autoplay);\n        break;\n      case 'preload':\n        if (newValue === oldValue) {\n          break;\n        }\n        this.#core?.setPreload(newValue as HTMLMediaElement['preload']);\n        break;\n      case Attributes.PLAYBACK_ID:\n        this.src = toMuxVideoURL(this) as string;\n        break;\n      case Attributes.DEBUG: {\n        const debug = this.debug;\n        if (!!this.mux) {\n          /** @TODO Link to docs for a more detailed discussion (CJP) */\n          console.info(\n            'Cannot toggle debug mode of mux data after initialization. Make sure you set all metadata to override before setting the src.'\n          );\n        }\n        if (!!this._hls) {\n          this._hls.config.debug = debug;\n        }\n        break;\n      }\n      case Attributes.METADATA_URL:\n        if (newValue) {\n          fetch(newValue)\n            .then((resp) => resp.json())\n            .then((json) => (this.metadata = json))\n            .catch(() => console.error(`Unable to load or parse metadata JSON from metadata-url ${newValue}!`));\n        }\n        break;\n      case Attributes.STREAM_TYPE:\n        // If the newValue is unset\n        if (newValue == null || newValue !== oldValue) {\n          this.dispatchEvent(new CustomEvent('streamtypechange', { composed: true, bubbles: true }));\n        }\n        break;\n      case Attributes.TARGET_LIVE_WINDOW:\n        if (newValue == null || newValue !== oldValue) {\n          this.dispatchEvent(\n            new CustomEvent('targetlivewindowchange', { composed: true, bubbles: true, detail: this.targetLiveWindow })\n          );\n        }\n        break;\n      default:\n        break;\n    }\n  }\n\n  connectedCallback(): void {\n    super.connectedCallback?.();\n    if (this.nativeEl && this.src && !this.#core) {\n      this.#requestLoad();\n    }\n  }\n\n  disconnectedCallback(): void {\n    this.unload();\n  }\n}\n\n// castable-video should be mixed in last so that it can override load().\nclass MuxVideoElement extends CastableMediaMixin(MediaTracksMixin(MuxVideoBaseElement)) {\n  // NOTE: CastableMediaMixin needs to be a subclass of whatever implements the load() method\n  // (i.e. MuxVideoBaseElement), but we're overriding castCustomData to provide mux-specific\n  // values by default, so it needs to be defined here (i.e. in the composed subclass of\n  // CastableMediaMixin). (CJP)\n  #castCustomData: Record<string, any> | undefined;\n\n  get muxCastCustomData() {\n    return {\n      mux: {\n        // Mux Video values\n        playbackId: this.playbackId,\n        minResolution: this.minResolution,\n        maxResolution: this.maxResolution,\n        renditionOrder: this.renditionOrder,\n        customDomain: this.customDomain,\n        /** @TODO Add this.tokens to MuxVideoElement (CJP) */\n        tokens: {\n          drm: this.drmToken,\n        },\n        // Mux Data values\n        envKey: this.envKey,\n        metadata: this.metadata,\n        disableCookies: this.disableCookies,\n        disableTracking: this.disableTracking,\n        beaconCollectionDomain: this.beaconCollectionDomain,\n        // Playback values\n        startTime: this.startTime,\n        // Other values\n        preferCmcd: this.preferCmcd,\n      },\n    } as const;\n  }\n\n  get castCustomData() {\n    return this.#castCustomData ?? this.muxCastCustomData;\n  }\n\n  set castCustomData(val: Record<string, any> | undefined) {\n    this.#castCustomData = val;\n  }\n}\n\ntype MuxVideoElementType = typeof MuxVideoElement;\ndeclare global {\n  var MuxVideoElement: MuxVideoElementType; // eslint-disable-line\n}\n\nif (!globalThis.customElements.get('mux-video')) {\n  globalThis.customElements.define('mux-video', MuxVideoElement);\n  globalThis.MuxVideoElement = MuxVideoElement;\n}\n\nexport { PlaybackEngine, PlaybackEngine as Hls, ExtensionMimeTypeMap as MimeTypes, MediaError, VideoEvents };\n\nexport default MuxVideoElement;\n", "export const isMaybeBrowser = () => typeof window != 'undefined';\n// @ts-ignore\nexport const isMaybeServer = () => typeof global != 'undefined';\n\nconst getEnvPlayerVersion = () => {\n  try {\n    // @ts-ignore\n    return PLAYER_VERSION as string;\n  } catch {}\n  return 'UNKNOWN';\n};\n\nconst player_version: string = getEnvPlayerVersion();\n\nexport const getPlayerVersion = () => player_version;\n", "/**\n * Custom Media Element\n * Based on https://github.com/muxinc/custom-video-element - Mux - MIT License\n *\n * The goal is to create an element that works just like the video element\n * but can be extended/sub-classed, because native elements cannot be\n * extended today across browsers.\n */\n\n// The onevent like props are weirdly set on the HTMLElement prototype with other\n// generic events making it impossible to pick these specific to HTMLMediaElement.\nexport const Events = [\n  'abort',\n  'canplay',\n  'canplaythrough',\n  'durationchange',\n  'emptied',\n  'encrypted',\n  'ended',\n  'error',\n  'loadeddata',\n  'loadedmetadata',\n  'loadstart',\n  'pause',\n  'play',\n  'playing',\n  'progress',\n  'ratechange',\n  'seeked',\n  'seeking',\n  'stalled',\n  'suspend',\n  'timeupdate',\n  'volumechange',\n  'waiting',\n  'waitingforkey',\n  'resize',\n  'enterpictureinpicture',\n  'leavepictureinpicture',\n  'webkitbeginfullscreen',\n  'webkitendfullscreen',\n  'webkitpresentationmodechanged',\n];\n\nfunction getAudioTemplateHTML(attrs) {\n  return /*html*/`\n    <style>\n      :host {\n        display: inline-flex;\n        line-height: 0;\n        flex-direction: column;\n        justify-content: end;\n      }\n\n      audio {\n        width: 100%;\n      }\n    </style>\n    <slot name=\"media\">\n      <audio${serializeAttributes(attrs)}></audio>\n    </slot>\n    <slot></slot>\n  `;\n}\n\n// If the `media` slot is used leave the styling up to the user.\n// It's a more consistent behavior pre and post custom element upgrade.\n\nfunction getVideoTemplateHTML(attrs) {\n  return /*html*/`\n    <style>\n      :host {\n        display: inline-block;\n        line-height: 0;\n      }\n\n      video {\n        max-width: 100%;\n        max-height: 100%;\n        min-width: 100%;\n        min-height: 100%;\n        object-fit: var(--media-object-fit, contain);\n        object-position: var(--media-object-position, 50% 50%);\n      }\n\n      video::-webkit-media-text-track-container {\n        transform: var(--media-webkit-text-track-transform);\n        transition: var(--media-webkit-text-track-transition);\n      }\n    </style>\n    <slot name=\"media\">\n      <video${serializeAttributes(attrs)}></video>\n    </slot>\n    <slot></slot>\n  `;\n}\n\n/**\n * @see https://justinfagnani.com/2015/12/21/real-mixins-with-javascript-classes/\n */\nexport const CustomMediaMixin = (superclass, { tag, is }) => {\n\n  // `is` makes it possible to extend a custom built-in. e.g. castable-video\n  const nativeElTest = globalThis.document?.createElement?.(tag, { is });\n  const nativeElProps = nativeElTest ? getNativeElProps(nativeElTest) : [];\n\n  return class CustomMedia extends superclass {\n    static getTemplateHTML = tag.endsWith('audio') ? getAudioTemplateHTML : getVideoTemplateHTML;\n    static shadowRootOptions = { mode: 'open' };\n    static Events = Events;\n    static #isDefined;\n\n    static get observedAttributes() {\n      CustomMedia.#define();\n\n      // Include any attributes from the custom built-in.\n      const natAttrs = nativeElTest?.constructor?.observedAttributes ?? [];\n\n      return [\n        ...natAttrs,\n        'autopictureinpicture',\n        'disablepictureinpicture',\n        'disableremoteplayback',\n        'autoplay',\n        'controls',\n        'controlslist',\n        'crossorigin',\n        'loop',\n        'muted',\n        'playsinline',\n        'poster',\n        'preload',\n        'src',\n      ];\n    }\n\n    static #define() {\n      if (this.#isDefined) return;\n      this.#isDefined = true;\n\n      const propsToAttrs = new Set(this.observedAttributes);\n      // defaultMuted maps to the muted attribute, handled manually below.\n      propsToAttrs.delete('muted');\n\n      // Passthrough native el functions from the custom el to the native el\n      for (let prop of nativeElProps) {\n        if (prop in this.prototype) continue;\n\n        const type = typeof nativeElTest[prop];\n        if (type == 'function') {\n          // Function\n          this.prototype[prop] = function (...args) {\n            this.#init();\n\n            const fn = () => {\n              if (this.call) return this.call(prop, ...args);\n              return this.nativeEl[prop].apply(this.nativeEl, args);\n            };\n\n            return fn();\n          };\n        } else {\n          // Some properties like src, preload, defaultMuted are handled manually.\n\n          // Getter\n          let config = {\n            get() {\n              this.#init();\n\n              let attr = prop.toLowerCase();\n              if (propsToAttrs.has(attr)) {\n                const val = this.getAttribute(attr);\n                return val === null ? false : val === '' ? true : val;\n              }\n\n              return this.get?.(prop) ?? this.nativeEl?.[prop];\n            },\n          };\n\n          if (prop !== prop.toUpperCase()) {\n            // Setter (not a CONSTANT)\n            config.set = function (val) {\n              this.#init();\n\n              let attr = prop.toLowerCase();\n              if (propsToAttrs.has(attr)) {\n                if (val === true || val === false || val == null) {\n                  this.toggleAttribute(attr, Boolean(val));\n                } else {\n                  this.setAttribute(attr, val);\n                }\n                return;\n              }\n\n              if (this.set) {\n                this.set(prop, val);\n                return;\n              }\n\n              this.nativeEl[prop] = val;\n            };\n          }\n\n          Object.defineProperty(this.prototype, prop, config);\n        }\n      }\n    }\n\n    #isInit;\n    #nativeEl;\n    #childMap = new Map();\n\n    constructor() {\n      super();\n\n      // If the custom element is defined before the custom element's HTML is parsed\n      // no attributes will be available in the constructor (construction process).\n      // Wait until initializing in the attributeChangedCallback or\n      // connectedCallback or accessing any properties.\n    }\n\n    get nativeEl() {\n      this.#init();\n      return this.#nativeEl\n        ?? this.shadowRoot.querySelector(tag)\n        ?? this.querySelector(':scope > [slot=media]')\n        ?? this.querySelector(tag);\n    }\n\n    set nativeEl(val) {\n      this.#nativeEl = val;\n    }\n\n    get defaultMuted() {\n      return this.hasAttribute('muted');\n    }\n\n    set defaultMuted(val) {\n      this.toggleAttribute('muted', Boolean(val));\n    }\n\n    get src() {\n      return this.getAttribute('src');\n    }\n\n    set src(val) {\n      this.setAttribute('src', `${val}`);\n    }\n\n    get preload() {\n      return this.getAttribute('preload') ?? this.nativeEl?.preload;\n    }\n\n    set preload(val) {\n      this.setAttribute('preload', `${val}`);\n    }\n\n    #init() {\n      if (this.#isInit) return;\n      this.#isInit = true;\n      this.init();\n    }\n\n    init() {\n      if (!this.shadowRoot) {\n        this.attachShadow({ mode: 'open' });\n\n        const attrs = namedNodeMapToObject(this.attributes);\n        if (is) attrs.is = is;\n        if (tag) attrs.part = tag;\n        this.shadowRoot.innerHTML = this.constructor.getTemplateHTML(attrs);\n      }\n\n      // Neither Chrome or Firefox support setting the muted attribute\n      // after using document.createElement.\n      // Get around this by setting the muted property manually.\n      this.nativeEl.muted = this.hasAttribute('muted');\n\n      for (let prop of nativeElProps) {\n        this.#upgradeProperty(prop);\n      }\n\n      this.shadowRoot.addEventListener('slotchange', this);\n      this.#syncMediaChildren();\n\n      for (let type of this.constructor.Events) {\n        this.shadowRoot.addEventListener?.(type, this, true);\n      }\n    }\n\n    handleEvent(event) {\n\n      if (event.type === 'slotchange') {\n        this.#syncMediaChildren();\n        return;\n      }\n\n      if (event.target === this.nativeEl) {\n        // The video events are dispatched on the CustomMediaElement instance.\n        // This makes it possible to add event listeners before the element is upgraded.\n        this.dispatchEvent(new CustomEvent(event.type, { detail: event.detail }));\n      }\n    }\n\n    /**\n     * Keep some native child elements like track and source in sync.\n     * An unnamed <slot> will be filled with all of the custom element's\n     * top-level child nodes that do not have the slot attribute.\n     */\n    #syncMediaChildren() {\n      const removeNativeChildren = new Map(this.#childMap);\n\n      this.shadowRoot.querySelector('slot:not([name])')\n        .assignedElements({ flatten: true })\n        .filter((el) => ['track', 'source'].includes(el.localName))\n        .forEach((el) => {\n          // If the source or track is still in the assigned elements keep it.\n          removeNativeChildren.delete(el);\n          // Re-use clones if possible.\n          let clone = this.#childMap.get(el);\n          if (!clone) {\n            clone = el.cloneNode();\n            this.#childMap.set(el, clone);\n          }\n          this.nativeEl.append?.(clone);\n\n          // https://html.spec.whatwg.org/multipage/media.html#sourcing-out-of-band-text-tracks\n          // If there are any text tracks in the media element's list of text\n          // tracks whose text track kind is chapters or metadata that\n          // correspond to track elements with a default attribute set whose\n          // text track mode is set to disabled, then set the text track\n          // mode of all such tracks to hidden.\n          if (\n            clone.localName === 'track' &&\n            clone.default &&\n            (clone.kind === 'chapters' || clone.kind === 'metadata') &&\n            clone.track.mode === 'disabled'\n          ) {\n            clone.track.mode = 'hidden';\n          }\n        });\n\n      removeNativeChildren.forEach((el) => el.remove());\n    }\n\n    #upgradeProperty(prop) {\n      // Sets properties that are set before the custom element is upgraded.\n      // https://web.dev/custom-elements-best-practices/#make-properties-lazy\n      if (Object.prototype.hasOwnProperty.call(this, prop)) {\n        const value = this[prop];\n        // Delete the set property from this instance.\n        delete this[prop];\n        // Set the value again via the (prototype) setter on this class.\n        this[prop] = value;\n      }\n    }\n\n    attributeChangedCallback(attrName, oldValue, newValue) {\n      // Initialize right after construction when the attributes become available.\n      this.#init();\n      this.#forwardAttribute(attrName, oldValue, newValue);\n    }\n\n    #forwardAttribute(attrName, oldValue, newValue) {\n      // Ignore a few that don't need to be passed.\n      if (['id', 'class'].includes(attrName)) {\n        return;\n      }\n\n      // Ignore setting custom attributes from the child class.\n      // They should not have any effect on the native element, it adds noise in the DOM.\n      if (!CustomMedia.observedAttributes.includes(attrName)\n        && this.constructor.observedAttributes.includes(attrName)\n      ) {\n        return;\n      }\n\n      if (newValue === null) {\n        this.nativeEl.removeAttribute?.(attrName);\n      } else {\n        if (this.nativeEl.getAttribute?.(attrName) != newValue) {\n          this.nativeEl.setAttribute?.(attrName, newValue);\n        }\n      }\n    }\n\n    connectedCallback() {\n      this.#init();\n    }\n  };\n};\n\nfunction getNativeElProps(nativeElTest) {\n  // Map all native element properties to the custom element\n  // so that they're applied to the native element.\n  // Skipping HTMLElement because of things like \"attachShadow\"\n  // causing issues. Most of those props still need to apply to\n  // the custom element.\n  let nativeElProps = [];\n\n  // Walk the prototype chain up to HTMLElement.\n  // This will grab all super class props in between.\n  // i.e. VideoElement and MediaElement\n  for (\n    let proto = Object.getPrototypeOf(nativeElTest);\n    proto && proto !== HTMLElement.prototype;\n    proto = Object.getPrototypeOf(proto)\n  ) {\n    nativeElProps.push(...Object.getOwnPropertyNames(proto));\n  }\n\n  return nativeElProps;\n}\n\nfunction serializeAttributes(attrs) {\n  let html = '';\n  for (const key in attrs) {\n    const value = attrs[key];\n    if (value === '') html += ` ${key}`;\n    else html += ` ${key}=\"${value}\"`;\n  }\n  return html;\n}\n\nfunction namedNodeMapToObject(namedNodeMap) {\n  let obj = {};\n  for (let attr of namedNodeMap) {\n    obj[attr.name] = attr.value;\n  }\n  return obj;\n}\n\nexport const CustomVideoElement = CustomMediaMixin(globalThis.HTMLElement ?? class {}, { tag: 'video' });\n\nexport const CustomAudioElement = CustomMediaMixin(globalThis.HTMLElement ?? class {}, { tag: 'audio' });\n", "/* global WeakRef */\n\nexport const privateProps = new WeakMap();\n\nexport class InvalidStateError extends Error {}\nexport class NotSupportedError extends Error {}\nexport class NotFoundError extends Error {}\n\n// Fallback to a plain Set if WeakRef is not available.\nexport const IterableWeakSet = globalThis.WeakRef ?\n  class extends Set {\n    add(el) {\n      super.add(new WeakRef(el));\n    }\n    forEach(fn) {\n      super.forEach((ref) => {\n        const value = ref.deref();\n        if (value) fn(value);\n      });\n    }\n  } : Set;\n\nexport function onCastApiAvailable(callback) {\n  if (!globalThis.chrome?.cast?.isAvailable) {\n    globalThis.__onGCastApiAvailable = () => {\n      // The globalThis.__onGCastApiAvailable callback alone is not reliable for\n      // the added cast.framework. It's loaded in a separate JS file.\n      // https://www.gstatic.com/eureka/clank/101/cast_sender.js\n      // https://www.gstatic.com/cast/sdk/libs/sender/1.0/cast_framework.js\n      customElements\n        .whenDefined('google-cast-button')\n        .then(callback);\n    };\n  } else if (!globalThis.cast?.framework) {\n    customElements\n      .whenDefined('google-cast-button')\n      .then(callback);\n  } else {\n    callback();\n  }\n}\n\nexport function requiresCastFramework() {\n  // todo: exclude for Android>=56 which supports the Remote Playback API natively.\n  return globalThis.chrome;\n}\n\nexport function loadCastFramework() {\n  const sdkUrl = 'https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1';\n  if (globalThis.chrome?.cast || document.querySelector(`script[src=\"${sdkUrl}\"]`)) return;\n\n  const script = document.createElement('script');\n  script.src = sdkUrl;\n  document.head.append(script);\n}\n\nexport function castContext() {\n  return globalThis.cast?.framework?.CastContext.getInstance();\n}\n\nexport function currentSession() {\n  return castContext()?.getCurrentSession();\n}\n\nexport function currentMedia() {\n  return currentSession()?.getSessionObj().media[0];\n}\n\nexport function editTracksInfo(request) {\n  return new Promise((resolve, reject) => {\n    currentMedia().editTracksInfo(request, resolve, reject);\n  });\n}\n\nexport function getMediaStatus(request) {\n  return new Promise((resolve, reject) => {\n    currentMedia().getStatus(request, resolve, reject);\n  });\n}\n\nexport function setCastOptions(options) {\n  return castContext().setOptions({\n    ...getDefaultCastOptions(),\n    ...options,\n  });\n}\n\nexport function getDefaultCastOptions() {\n  return {\n    // Set the receiver application ID to your own (created in the\n    // Google Cast Developer Console), or optionally\n    // use the chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID\n    receiverApplicationId: 'CC1AD845',\n\n    // Auto join policy can be one of the following three:\n    // ORIGIN_SCOPED - Auto connect from same appId and page origin\n    // TAB_AND_ORIGIN_SCOPED - Auto connect from same appId, page origin, and tab\n    // PAGE_SCOPED - No auto connect\n    autoJoinPolicy: 'origin_scoped',\n\n    // The following flag enables Cast Connect(requires Chrome 87 or higher)\n    // https://developers.googleblog.com/2020/08/introducing-cast-connect-android-tv.html\n    androidReceiverCompatible: false,\n\n    language: 'en-US',\n    resumeSavedSession: true,\n  };\n}\n", "/* global chrome, cast */\nimport {\n  privateProps,\n  IterableWeakSet,\n  InvalidStateError,\n  NotSupportedError,\n  onCastApiAvailable,\n  castContext,\n  currentSession,\n  currentMedia,\n  editTracksInfo,\n  getMediaStatus,\n  setCastOptions\n} from './castable-utils.js';\n\nconst remoteInstances = new IterableWeakSet();\nconst castElementRef = new WeakSet();\n\nlet cf;\n\nonCastApiAvailable(() => {\n  if (!globalThis.chrome?.cast?.isAvailable) {\n    // Useful to see in verbose logs if this shows undefined or false.\n    console.debug('chrome.cast.isAvailable', globalThis.chrome?.cast?.isAvailable);\n    return;\n  }\n\n  if (!cf) {\n    cf = cast.framework;\n\n    castContext().addEventListener(cf.CastContextEventType.CAST_STATE_CHANGED, (e) => {\n      remoteInstances.forEach((r) => privateProps.get(r).onCastStateChanged?.(e));\n    });\n\n    castContext().addEventListener(cf.CastContextEventType.SESSION_STATE_CHANGED, (e) => {\n      remoteInstances.forEach((r) => privateProps.get(r).onSessionStateChanged?.(e));\n    });\n\n    remoteInstances.forEach((r) => privateProps.get(r).init?.());\n  }\n});\n\n\nlet remotePlaybackCallbackIdCount = 0;\n\n/**\n * Remote Playback shim for the Google cast SDK.\n * https://w3c.github.io/remote-playback/\n */\nexport class RemotePlayback extends EventTarget {\n  #media;\n  #isInit;\n  #remotePlayer;\n  #remoteListeners;\n  #state = 'disconnected';\n  #available = false;\n  #callbacks = new Set();\n  #callbackIds = new WeakMap();\n\n  constructor(media) {\n    super();\n\n    this.#media = media;\n\n    remoteInstances.add(this);\n    privateProps.set(this, {\n      init: () => this.#init(),\n      onCastStateChanged: () => this.#onCastStateChanged(),\n      onSessionStateChanged: () => this.#onSessionStateChanged(),\n      getCastPlayer: () => this.#castPlayer,\n    });\n\n    this.#init();\n  }\n\n  get #castPlayer() {\n    if (castElementRef.has(this.#media)) return this.#remotePlayer;\n    return undefined;\n  }\n\n  /**\n   * https://developer.mozilla.org/en-US/docs/Web/API/RemotePlayback/state\n   * @return {'disconnected'|'connecting'|'connected'}\n   */\n  get state() {\n    return this.#state;\n  }\n\n  async watchAvailability(callback) {\n    if (this.#media.disableRemotePlayback) {\n      throw new InvalidStateError('disableRemotePlayback attribute is present.');\n    }\n\n    this.#callbackIds.set(callback, ++remotePlaybackCallbackIdCount);\n    this.#callbacks.add(callback);\n\n    return remotePlaybackCallbackIdCount;\n  }\n\n  async cancelWatchAvailability(callback) {\n    if (this.#media.disableRemotePlayback) {\n      throw new InvalidStateError('disableRemotePlayback attribute is present.');\n    }\n\n    if (callback) {\n      this.#callbacks.delete(callback);\n    } else {\n      this.#callbacks.clear();\n    }\n  }\n\n  async prompt() {\n    if (this.#media.disableRemotePlayback) {\n      throw new InvalidStateError('disableRemotePlayback attribute is present.');\n    }\n\n    if (!globalThis.chrome?.cast?.isAvailable) {\n      throw new NotSupportedError('The RemotePlayback API is disabled on this platform.');\n    }\n\n    const willDisconnect = castElementRef.has(this.#media);\n    castElementRef.add(this.#media);\n\n    setCastOptions(this.#media.castOptions);\n\n    Object.entries(this.#remoteListeners).forEach(([event, listener]) => {\n      this.#remotePlayer.controller.addEventListener(event, listener);\n    });\n\n    try {\n      // Open browser cast menu.\n      await castContext().requestSession();\n    } catch (err) {\n      // Don't throw an error if disconnecting or cancelling.\n      if (err === 'cancel') {\n        // If there will be no disconnect, reset some state here.\n        if (!willDisconnect) {\n          castElementRef.delete(this.#media);\n        }\n        return;\n      }\n\n      throw new Error(err);\n    }\n\n    privateProps.get(this.#media)?.loadOnPrompt?.();\n  }\n\n  #disconnect() {\n    if (!castElementRef.has(this.#media)) return;\n\n    Object.entries(this.#remoteListeners).forEach(([event, listener]) => {\n      this.#remotePlayer.controller.removeEventListener(event, listener);\n    });\n\n    castElementRef.delete(this.#media);\n\n    // isMuted is not in savedPlayerState. should we sync this back to local?\n    this.#media.muted = this.#remotePlayer.isMuted;\n    this.#media.currentTime = this.#remotePlayer.savedPlayerState.currentTime;\n    if (this.#remotePlayer.savedPlayerState.isPaused === false) {\n      this.#media.play();\n    }\n  }\n\n  #onCastStateChanged() {\n    // Cast state: NO_DEVICES_AVAILABLE, NOT_CONNECTED, CONNECTING, CONNECTED\n    // https://developers.google.com/cast/docs/reference/web_sender/cast.framework#.CastState\n    const castState = castContext().getCastState();\n\n    if (castElementRef.has(this.#media)) {\n      if (castState === 'CONNECTING') {\n        this.#state = 'connecting';\n        this.dispatchEvent(new Event('connecting'));\n      }\n    }\n\n    if (!this.#available && castState?.includes('CONNECT')) {\n      this.#available = true;\n      for (let callback of this.#callbacks) callback(true);\n    }\n    else if (this.#available && (!castState || castState === 'NO_DEVICES_AVAILABLE')) {\n      this.#available = false;\n      for (let callback of this.#callbacks) callback(false);\n    }\n  }\n\n  async #onSessionStateChanged() {\n    // Session states: NO_SESSION, SESSION_STARTING, SESSION_STARTED, SESSION_START_FAILED,\n    //                 SESSION_ENDING, SESSION_ENDED, SESSION_RESUMED\n    // https://developers.google.com/cast/docs/reference/web_sender/cast.framework#.SessionState\n\n    const { SESSION_RESUMED } = cf.SessionState;\n    if (castContext().getSessionState() === SESSION_RESUMED) {\n      /**\n       * Figure out if this was the video that started the resumed session.\n       * @TODO make this more specific than just checking against the video src!! (WL)\n       *\n       * If this video element can get the same unique id on each browser refresh\n       * it would be possible to pass this unique id w/ `LoadRequest.customData`\n       * and verify against currentMedia().customData below.\n       */\n      if (this.#media.castSrc === currentMedia()?.media.contentId) {\n        castElementRef.add(this.#media);\n\n        Object.entries(this.#remoteListeners).forEach(([event, listener]) => {\n          this.#remotePlayer.controller.addEventListener(event, listener);\n        });\n\n        /**\n         * There is cast framework resume session bug when you refresh the page a few\n         * times the this.#remotePlayer.currentTime will not be in sync with the receiver :(\n         * The below status request syncs it back up.\n         */\n        try {\n          await getMediaStatus(new chrome.cast.media.GetStatusRequest());\n        } catch (error) {\n          console.error(error);\n        }\n\n        // Dispatch the play, playing events manually to sync remote playing state.\n        this.#remoteListeners[cf.RemotePlayerEventType.IS_PAUSED_CHANGED]();\n        this.#remoteListeners[cf.RemotePlayerEventType.PLAYER_STATE_CHANGED]();\n      }\n    }\n  }\n\n  #init() {\n    if (!cf || this.#isInit) return;\n    this.#isInit = true;\n\n    setCastOptions(this.#media.castOptions);\n\n    /**\n     * @TODO add listeners for addtrack, removetrack (WL)\n     * This only has an impact on <track> with a `src` because these have to be\n     * loaded manually in the load() method. This will require a new load() call\n     * for each added/removed track w/ src.\n     */\n    this.#media.textTracks.addEventListener('change', () => this.#updateRemoteTextTrack());\n\n    this.#onCastStateChanged();\n\n    this.#remotePlayer = new cf.RemotePlayer();\n    new cf.RemotePlayerController(this.#remotePlayer);\n\n    this.#remoteListeners = {\n      [cf.RemotePlayerEventType.IS_CONNECTED_CHANGED]: ({ value }) => {\n        if (value === true) {\n          this.#state = 'connected';\n          this.dispatchEvent(new Event('connect'));\n        } else {\n          this.#disconnect();\n          this.#state = 'disconnected';\n          this.dispatchEvent(new Event('disconnect'));\n        }\n      },\n      [cf.RemotePlayerEventType.DURATION_CHANGED]: () => {\n        this.#media.dispatchEvent(new Event('durationchange'));\n      },\n      [cf.RemotePlayerEventType.VOLUME_LEVEL_CHANGED]: () => {\n        this.#media.dispatchEvent(new Event('volumechange'));\n      },\n      [cf.RemotePlayerEventType.IS_MUTED_CHANGED]: () => {\n        this.#media.dispatchEvent(new Event('volumechange'));\n      },\n      [cf.RemotePlayerEventType.CURRENT_TIME_CHANGED]: () => {\n        if (!this.#castPlayer?.isMediaLoaded) return;\n        this.#media.dispatchEvent(new Event('timeupdate'));\n      },\n      [cf.RemotePlayerEventType.VIDEO_INFO_CHANGED]: () => {\n        this.#media.dispatchEvent(new Event('resize'));\n      },\n      [cf.RemotePlayerEventType.IS_PAUSED_CHANGED]: () => {\n        this.#media.dispatchEvent(new Event(this.paused ? 'pause' : 'play'));\n      },\n      [cf.RemotePlayerEventType.PLAYER_STATE_CHANGED]: () => {\n        // Player states: IDLE, PLAYING, PAUSED, BUFFERING\n        // https://developers.google.com/cast/docs/reference/web_sender/chrome.cast.media#.PlayerState\n\n        // pause event is handled above.\n        if (this.#castPlayer?.playerState === chrome.cast.media.PlayerState.PAUSED) {\n          return;\n        }\n\n        this.#media.dispatchEvent(\n          new Event(\n            {\n              [chrome.cast.media.PlayerState.PLAYING]: 'playing',\n              [chrome.cast.media.PlayerState.BUFFERING]: 'waiting',\n              [chrome.cast.media.PlayerState.IDLE]: 'emptied',\n            }[this.#castPlayer?.playerState]\n          )\n        );\n      },\n      [cf.RemotePlayerEventType.IS_MEDIA_LOADED_CHANGED]: async () => {\n        if (!this.#castPlayer?.isMediaLoaded) return;\n\n        // mediaInfo is not immediately available due to a bug? wait one tick\n        await Promise.resolve();\n        this.#onRemoteMediaLoaded();\n      },\n    };\n  }\n\n  #onRemoteMediaLoaded() {\n    this.#updateRemoteTextTrack();\n  }\n\n  async #updateRemoteTextTrack() {\n    if (!this.#castPlayer) return;\n\n    // Get the tracks w/ trackId's that have been loaded; manually or via a playlist like a M3U8 or MPD.\n    const remoteTracks = this.#remotePlayer.mediaInfo?.tracks ?? [];\n    const remoteSubtitles = remoteTracks.filter(\n      ({ type }) => type === chrome.cast.media.TrackType.TEXT\n    );\n\n    const localSubtitles = [...this.#media.textTracks].filter(\n      ({ kind }) => kind === 'subtitles' || kind === 'captions'\n    );\n\n    // Create a new array from the local subs w/ the trackId's from the remote subs.\n    const subtitles = remoteSubtitles\n      .map(({ language, name, trackId }) => {\n        // Find the corresponding local text track and assign the trackId.\n        const { mode } =\n          localSubtitles.find(\n            (local) => local.language === language && local.label === name\n          ) ?? {};\n        if (mode) return { mode, trackId };\n        return false;\n      })\n      .filter(Boolean);\n\n    const hiddenSubtitles = subtitles.filter(\n      ({ mode }) => mode !== 'showing'\n    );\n    const hiddenTrackIds = hiddenSubtitles.map(({ trackId }) => trackId);\n    const showingSubtitle = subtitles.find(({ mode }) => mode === 'showing');\n\n    // Note this could also include audio or video tracks, diff against local state.\n    const activeTrackIds =\n      currentSession()?.getSessionObj().media[0]\n        ?.activeTrackIds ?? [];\n    let requestTrackIds = activeTrackIds;\n\n    if (activeTrackIds.length) {\n      // Filter out all local hidden subtitle trackId's.\n      requestTrackIds = requestTrackIds.filter(\n        (id) => !hiddenTrackIds.includes(id)\n      );\n    }\n\n    if (showingSubtitle?.trackId) {\n      requestTrackIds = [...requestTrackIds, showingSubtitle.trackId];\n    }\n\n    // Remove duplicate ids.\n    requestTrackIds = [...new Set(requestTrackIds)];\n\n    const arrayEquals = (a, b) =>\n      a.length === b.length && a.every((a) => b.includes(a));\n    if (!arrayEquals(activeTrackIds, requestTrackIds)) {\n      try {\n        const request = new chrome.cast.media.EditTracksInfoRequest(\n          requestTrackIds\n        );\n        await editTracksInfo(request);\n      } catch (error) {\n        console.error(error);\n      }\n    }\n  }\n}\n", "/* global chrome */\nimport { RemotePlayback } from './castable-remote-playback.js';\nimport {\n  privateProps,\n  requiresCastFramework,\n  loadCastFramework,\n  currentSession,\n  getDefaultCastOptions\n} from './castable-utils.js';\n\n/**\n * CastableMediaMixin\n *\n * This mixin function provides a way to compose multiple classes.\n * @see https://justinfagnani.com/2015/12/21/real-mixins-with-javascript-classes/\n *\n * @param  {HTMLMediaElement} superclass - HTMLMediaElement or an extended class of it.\n * @return {CastableMedia}\n */\nexport const CastableMediaMixin = (superclass) =>\n  class CastableMedia extends superclass {\n\n    static observedAttributes = [\n      ...(superclass.observedAttributes ?? []),\n      'cast-src',\n      'cast-content-type',\n      'cast-stream-type',\n      'cast-receiver',\n    ];\n\n    #localState = { paused: false };\n    #castOptions = getDefaultCastOptions();\n    #castCustomData;\n    #remote;\n\n    get remote() {\n      if (this.#remote) return this.#remote;\n\n      if (requiresCastFramework()) {\n        loadCastFramework();\n\n        privateProps.set(this, {\n          loadOnPrompt: () => this.#loadOnPrompt()\n        });\n\n        return (this.#remote = new RemotePlayback(this));\n      }\n\n      return super.remote;\n    }\n\n    get #castPlayer() {\n      return privateProps.get(this.remote)?.getCastPlayer?.();\n    }\n\n    attributeChangedCallback(attrName, oldValue, newValue) {\n      super.attributeChangedCallback(attrName, oldValue, newValue);\n\n      if (attrName === 'cast-receiver' && newValue) {\n        this.#castOptions.receiverApplicationId = newValue;\n        return;\n      }\n\n      if (!this.#castPlayer) return;\n\n      switch (attrName) {\n        case 'cast-stream-type':\n        case 'cast-src':\n          this.load();\n          break;\n      }\n    }\n\n    async #loadOnPrompt() {\n      // Pause locally when the session is created.\n      this.#localState.paused = super.paused;\n      super.pause();\n\n      // Sync over the muted state but not volume, 100% is different on TV's :P\n      this.muted = super.muted;\n\n      try {\n        await this.load();\n      } catch (err) {\n        console.error(err);\n      }\n    }\n\n    async load() {\n      if (!this.#castPlayer) return super.load();\n\n      const mediaInfo = new chrome.cast.media.MediaInfo(this.castSrc, this.castContentType);\n      mediaInfo.customData = this.castCustomData;\n\n      // Manually add text tracks with a `src` attribute.\n      // M3U8's load text tracks in the receiver, handle these in the media loaded event.\n      const subtitles = [...this.querySelectorAll('track')].filter(\n        ({ kind, src }) => src && (kind === 'subtitles' || kind === 'captions')\n      );\n\n      const activeTrackIds = [];\n      let textTrackIdCount = 0;\n\n      if (subtitles.length) {\n        mediaInfo.tracks = subtitles.map((trackEl) => {\n          const trackId = ++textTrackIdCount;\n          // only activate 1 subtitle text track.\n          if (activeTrackIds.length === 0 && trackEl.track.mode === 'showing') {\n            activeTrackIds.push(trackId);\n          }\n\n          const track = new chrome.cast.media.Track(\n            trackId,\n            chrome.cast.media.TrackType.TEXT\n          );\n          track.trackContentId = trackEl.src;\n          track.trackContentType = 'text/vtt';\n          track.subtype =\n            trackEl.kind === 'captions'\n              ? chrome.cast.media.TextTrackType.CAPTIONS\n              : chrome.cast.media.TextTrackType.SUBTITLES;\n          track.name = trackEl.label;\n          track.language = trackEl.srclang;\n          return track;\n        });\n      }\n\n      if (this.castStreamType === 'live') {\n        mediaInfo.streamType = chrome.cast.media.StreamType.LIVE;\n      } else {\n        mediaInfo.streamType = chrome.cast.media.StreamType.BUFFERED;\n      }\n\n      mediaInfo.metadata = new chrome.cast.media.GenericMediaMetadata();\n      mediaInfo.metadata.title = this.title;\n      mediaInfo.metadata.images = [{ url: this.poster }];\n\n      const request = new chrome.cast.media.LoadRequest(mediaInfo);\n      request.currentTime = super.currentTime ?? 0;\n      request.autoplay = !this.#localState.paused;\n      request.activeTrackIds = activeTrackIds;\n\n      await currentSession()?.loadMedia(request);\n\n      this.dispatchEvent(new Event('volumechange'));\n    }\n\n    play() {\n      if (this.#castPlayer) {\n        if (this.#castPlayer.isPaused) {\n          this.#castPlayer.controller?.playOrPause();\n        }\n        return;\n      }\n      return super.play();\n    }\n\n    pause() {\n      if (this.#castPlayer) {\n        if (!this.#castPlayer.isPaused) {\n          this.#castPlayer.controller?.playOrPause();\n        }\n        return;\n      }\n      super.pause();\n    }\n\n    /**\n     * @see https://developers.google.com/cast/docs/reference/web_sender/cast.framework.CastOptions\n     * @readonly\n     *\n     * @typedef {Object} CastOptions\n     * @property {string} [receiverApplicationId='CC1AD845'] - The app id of the cast receiver.\n     * @property {string} [autoJoinPolicy='origin_scoped'] - The auto join policy.\n     * @property {string} [language='en-US'] - The language to use for the cast receiver.\n     * @property {boolean} [androidReceiverCompatible=false] - Whether to use the Cast Connect.\n     * @property {boolean} [resumeSavedSession=true] - Whether to resume the last session.\n     *\n     * @return {CastOptions}\n     */\n    get castOptions() {\n      return this.#castOptions;\n    }\n\n    get castReceiver() {\n      return this.getAttribute('cast-receiver') ?? undefined;\n    }\n\n    set castReceiver(val) {\n      if (this.castReceiver == val) return;\n      this.setAttribute('cast-receiver', `${val}`);\n    }\n\n    // Allow the cast source url to be different than <video src>, could be a blob.\n    get castSrc() {\n      // Try the first <source src> for usage with even more native markup.\n      return (\n        this.getAttribute('cast-src') ??\n        this.querySelector('source')?.src ??\n        this.currentSrc\n      );\n    }\n\n    set castSrc(val) {\n      if (this.castSrc == val) return;\n      this.setAttribute('cast-src', `${val}`);\n    }\n\n    get castContentType() {\n      return this.getAttribute('cast-content-type') ?? undefined;\n    }\n\n    set castContentType(val) {\n      this.setAttribute('cast-content-type', `${val}`);\n    }\n\n    get castStreamType() {\n      // NOTE: Per https://github.com/video-dev/media-ui-extensions/issues/3 `streamType` may yield `\"unknown\"`\n      return this.getAttribute('cast-stream-type') ?? this.streamType ?? undefined;\n    }\n\n    set castStreamType(val) {\n      this.setAttribute('cast-stream-type', `${val}`);\n    }\n\n    get castCustomData() {\n      return this.#castCustomData;\n    }\n\n    set castCustomData(val) {\n      const valType = typeof val;\n      if (!['object', 'undefined'].includes(valType)) {\n        console.error(`castCustomData must be nullish or an object but value was of type ${valType}`);\n        return;\n      }\n\n      this.#castCustomData = val;\n    }\n\n    get readyState() {\n      if (this.#castPlayer) {\n        switch (this.#castPlayer.playerState) {\n          case chrome.cast.media.PlayerState.IDLE:\n            return 0;\n          case chrome.cast.media.PlayerState.BUFFERING:\n            return 2;\n          default:\n            return 3;\n        }\n      }\n      return super.readyState;\n    }\n\n    get paused() {\n      if (this.#castPlayer) return this.#castPlayer.isPaused;\n      return super.paused;\n    }\n\n    get muted() {\n      if (this.#castPlayer) return this.#castPlayer?.isMuted;\n      return super.muted;\n    }\n\n    set muted(val) {\n      if (this.#castPlayer) {\n        if (\n          (val && !this.#castPlayer.isMuted) ||\n          (!val && this.#castPlayer.isMuted)\n        ) {\n          this.#castPlayer.controller?.muteOrUnmute();\n        }\n        return;\n      }\n      super.muted = val;\n    }\n\n    get volume() {\n      if (this.#castPlayer) return this.#castPlayer?.volumeLevel ?? 1;\n      return super.volume;\n    }\n\n    set volume(val) {\n      if (this.#castPlayer) {\n        this.#castPlayer.volumeLevel = +val;\n        this.#castPlayer.controller?.setVolumeLevel();\n        return;\n      }\n      super.volume = val;\n    }\n\n    get duration() {\n      // castPlayer duration returns `0` when no media is loaded.\n      if (this.#castPlayer && this.#castPlayer?.isMediaLoaded) {\n        return this.#castPlayer?.duration ?? NaN;\n      }\n      return super.duration;\n    }\n\n    get currentTime() {\n      if (this.#castPlayer && this.#castPlayer?.isMediaLoaded) {\n        return this.#castPlayer?.currentTime ?? 0;\n      }\n      return super.currentTime;\n    }\n\n    set currentTime(val) {\n      if (this.#castPlayer) {\n        this.#castPlayer.currentTime = val;\n        this.#castPlayer.controller?.seek();\n        return;\n      }\n      super.currentTime = val;\n    }\n  };\n\nexport const CastableVideoMixin = CastableMediaMixin;\n", "class TrackEvent extends Event {\n  track;\n  constructor(type, init) {\n    super(type);\n    this.track = init.track;\n  }\n}\nexport {\n  TrackEvent\n};\n", "const privateProps = /* @__PURE__ */ new WeakMap();\nfunction getPrivate(instance) {\n  return privateProps.get(instance) ?? setPrivate(instance, {});\n}\nfunction setPrivate(instance, props) {\n  let saved = privateProps.get(instance);\n  if (!saved) privateProps.set(instance, saved = {});\n  return Object.assign(saved, props);\n}\nexport {\n  getPrivate,\n  setPrivate\n};\n", "import { TrackEvent } from \"./track-event.js\";\nimport { getPrivate } from \"./utils.js\";\nfunction addVideoTrack(media, track) {\n  const trackList = media.videoTracks;\n  getPrivate(track).media = media;\n  if (!getPrivate(track).renditionSet) {\n    getPrivate(track).renditionSet = /* @__PURE__ */ new Set();\n  }\n  const trackSet = getPrivate(trackList).trackSet;\n  trackSet.add(track);\n  const index = trackSet.size - 1;\n  if (!(index in VideoTrackList.prototype)) {\n    Object.defineProperty(VideoTrackList.prototype, index, {\n      get() {\n        return [...getPrivate(this).trackSet][index];\n      }\n    });\n  }\n  queueMicrotask(() => {\n    trackList.dispatchEvent(new TrackEvent(\"addtrack\", { track }));\n  });\n}\nfunction removeVideoTrack(track) {\n  const trackList = getPrivate(track).media?.videoTracks;\n  if (!trackList) return;\n  const trackSet = getPrivate(trackList).trackSet;\n  trackSet.delete(track);\n  queueMicrotask(() => {\n    trackList.dispatchEvent(new TrackEvent(\"removetrack\", { track }));\n  });\n}\nfunction selectedChanged(selected) {\n  const trackList = getPrivate(selected).media.videoTracks ?? [];\n  let hasUnselected = false;\n  for (const track of trackList) {\n    if (track === selected) continue;\n    track.selected = false;\n    hasUnselected = true;\n  }\n  if (hasUnselected) {\n    if (getPrivate(trackList).changeRequested) return;\n    getPrivate(trackList).changeRequested = true;\n    queueMicrotask(() => {\n      delete getPrivate(trackList).changeRequested;\n      trackList.dispatchEvent(new Event(\"change\"));\n    });\n  }\n}\nclass VideoTrackList extends EventTarget {\n  #addTrackCallback;\n  #removeTrackCallback;\n  #changeCallback;\n  constructor() {\n    super();\n    getPrivate(this).trackSet = /* @__PURE__ */ new Set();\n  }\n  get #tracks() {\n    return getPrivate(this).trackSet;\n  }\n  [Symbol.iterator]() {\n    return this.#tracks.values();\n  }\n  get length() {\n    return this.#tracks.size;\n  }\n  getTrackById(id) {\n    return [...this.#tracks].find((track) => track.id === id) ?? null;\n  }\n  get selectedIndex() {\n    return [...this.#tracks].findIndex((track) => track.selected);\n  }\n  get onaddtrack() {\n    return this.#addTrackCallback;\n  }\n  set onaddtrack(callback) {\n    if (this.#addTrackCallback) {\n      this.removeEventListener(\"addtrack\", this.#addTrackCallback);\n      this.#addTrackCallback = void 0;\n    }\n    if (typeof callback == \"function\") {\n      this.#addTrackCallback = callback;\n      this.addEventListener(\"addtrack\", callback);\n    }\n  }\n  get onremovetrack() {\n    return this.#removeTrackCallback;\n  }\n  set onremovetrack(callback) {\n    if (this.#removeTrackCallback) {\n      this.removeEventListener(\"removetrack\", this.#removeTrackCallback);\n      this.#removeTrackCallback = void 0;\n    }\n    if (typeof callback == \"function\") {\n      this.#removeTrackCallback = callback;\n      this.addEventListener(\"removetrack\", callback);\n    }\n  }\n  get onchange() {\n    return this.#changeCallback;\n  }\n  set onchange(callback) {\n    if (this.#changeCallback) {\n      this.removeEventListener(\"change\", this.#changeCallback);\n      this.#changeCallback = void 0;\n    }\n    if (typeof callback == \"function\") {\n      this.#changeCallback = callback;\n      this.addEventListener(\"change\", callback);\n    }\n  }\n}\nexport {\n  VideoTrackList,\n  addVideoTrack,\n  removeVideoTrack,\n  selectedChanged\n};\n", "class RenditionEvent extends Event {\n  rendition;\n  constructor(type, init) {\n    super(type);\n    this.rendition = init.rendition;\n  }\n}\nexport {\n  RenditionEvent\n};\n", "import { RenditionEvent } from \"./rendition-event.js\";\nimport { getPrivate } from \"./utils.js\";\nfunction addRendition(track, rendition) {\n  const renditionList = getPrivate(track).media.videoRenditions;\n  getPrivate(rendition).media = getPrivate(track).media;\n  getPrivate(rendition).track = track;\n  const renditionSet = getPrivate(track).renditionSet;\n  renditionSet.add(rendition);\n  const index = renditionSet.size - 1;\n  if (!(index in VideoRenditionList.prototype)) {\n    Object.defineProperty(VideoRenditionList.prototype, index, {\n      get() {\n        return getCurrentRenditions(this)[index];\n      }\n    });\n  }\n  queueMicrotask(() => {\n    if (!track.selected) return;\n    renditionList.dispatchEvent(new RenditionEvent(\"addrendition\", { rendition }));\n  });\n}\nfunction removeRendition(rendition) {\n  const renditionList = getPrivate(rendition).media.videoRenditions;\n  const track = getPrivate(rendition).track;\n  const renditionSet = getPrivate(track).renditionSet;\n  renditionSet.delete(rendition);\n  queueMicrotask(() => {\n    const track2 = getPrivate(rendition).track;\n    if (!track2.selected) return;\n    renditionList.dispatchEvent(new RenditionEvent(\"removerendition\", { rendition }));\n  });\n}\nfunction selectedChanged(rendition) {\n  const renditionList = getPrivate(rendition).media.videoRenditions;\n  if (!renditionList || getPrivate(renditionList).changeRequested) return;\n  getPrivate(renditionList).changeRequested = true;\n  queueMicrotask(() => {\n    delete getPrivate(renditionList).changeRequested;\n    const track = getPrivate(rendition).track;\n    if (!track.selected) return;\n    renditionList.dispatchEvent(new Event(\"change\"));\n  });\n}\nfunction getCurrentRenditions(renditionList) {\n  const media = getPrivate(renditionList).media;\n  return [...media.videoTracks].filter((track) => track.selected).flatMap((track) => [...getPrivate(track).renditionSet]);\n}\nclass VideoRenditionList extends EventTarget {\n  #addRenditionCallback;\n  #removeRenditionCallback;\n  #changeCallback;\n  [Symbol.iterator]() {\n    return getCurrentRenditions(this).values();\n  }\n  get length() {\n    return getCurrentRenditions(this).length;\n  }\n  getRenditionById(id) {\n    return getCurrentRenditions(this).find((rendition) => `${rendition.id}` === `${id}`) ?? null;\n  }\n  get selectedIndex() {\n    return getCurrentRenditions(this).findIndex((rendition) => rendition.selected);\n  }\n  set selectedIndex(index) {\n    for (const [i, rendition] of getCurrentRenditions(this).entries()) {\n      rendition.selected = i === index;\n    }\n  }\n  get onaddrendition() {\n    return this.#addRenditionCallback;\n  }\n  set onaddrendition(callback) {\n    if (this.#addRenditionCallback) {\n      this.removeEventListener(\"addrendition\", this.#addRenditionCallback);\n      this.#addRenditionCallback = void 0;\n    }\n    if (typeof callback == \"function\") {\n      this.#addRenditionCallback = callback;\n      this.addEventListener(\"addrendition\", callback);\n    }\n  }\n  get onremoverendition() {\n    return this.#removeRenditionCallback;\n  }\n  set onremoverendition(callback) {\n    if (this.#removeRenditionCallback) {\n      this.removeEventListener(\"removerendition\", this.#removeRenditionCallback);\n      this.#removeRenditionCallback = void 0;\n    }\n    if (typeof callback == \"function\") {\n      this.#removeRenditionCallback = callback;\n      this.addEventListener(\"removerendition\", callback);\n    }\n  }\n  get onchange() {\n    return this.#changeCallback;\n  }\n  set onchange(callback) {\n    if (this.#changeCallback) {\n      this.removeEventListener(\"change\", this.#changeCallback);\n      this.#changeCallback = void 0;\n    }\n    if (typeof callback == \"function\") {\n      this.#changeCallback = callback;\n      this.addEventListener(\"change\", callback);\n    }\n  }\n}\nexport {\n  VideoRenditionList,\n  addRendition,\n  removeRendition,\n  selectedChanged\n};\n", "import { selectedChanged } from \"./video-rendition-list.js\";\nclass VideoRendition {\n  src;\n  id;\n  width;\n  height;\n  bitrate;\n  frameRate;\n  codec;\n  #selected = false;\n  get selected() {\n    return this.#selected;\n  }\n  set selected(val) {\n    if (this.#selected === val) return;\n    this.#selected = val;\n    selectedChanged(this);\n  }\n}\nexport {\n  VideoRendition\n};\n", "import { selectedChanged } from \"./video-track-list.js\";\nimport { VideoRendition } from \"./video-rendition.js\";\nimport { addRendition, removeRendition } from \"./video-rendition-list.js\";\nconst VideoTrackKind = {\n  alternative: \"alternative\",\n  captions: \"captions\",\n  main: \"main\",\n  sign: \"sign\",\n  subtitles: \"subtitles\",\n  commentary: \"commentary\"\n};\nclass VideoTrack {\n  id;\n  kind;\n  label = \"\";\n  language = \"\";\n  sourceBuffer;\n  #selected = false;\n  addRendition(src, width, height, codec, bitrate, frameRate) {\n    const rendition = new VideoRendition();\n    rendition.src = src;\n    rendition.width = width;\n    rendition.height = height;\n    rendition.frameRate = frameRate;\n    rendition.bitrate = bitrate;\n    rendition.codec = codec;\n    addRendition(this, rendition);\n    return rendition;\n  }\n  removeRendition(rendition) {\n    removeRendition(rendition);\n  }\n  get selected() {\n    return this.#selected;\n  }\n  set selected(val) {\n    if (this.#selected === val) return;\n    this.#selected = val;\n    if (val !== true) return;\n    selectedChanged(this);\n  }\n}\nexport {\n  VideoTrack,\n  VideoTrackKind\n};\n", "import { RenditionEvent } from \"./rendition-event.js\";\nimport { getPrivate } from \"./utils.js\";\nfunction addRendition(track, rendition) {\n  const renditionList = getPrivate(track).media.audioRenditions;\n  getPrivate(rendition).media = getPrivate(track).media;\n  getPrivate(rendition).track = track;\n  const renditionSet = getPrivate(track).renditionSet;\n  renditionSet.add(rendition);\n  const index = renditionSet.size - 1;\n  if (!(index in AudioRenditionList.prototype)) {\n    Object.defineProperty(AudioRenditionList.prototype, index, {\n      get() {\n        return getCurrentRenditions(this)[index];\n      }\n    });\n  }\n  queueMicrotask(() => {\n    if (!track.enabled) return;\n    renditionList.dispatchEvent(new RenditionEvent(\"addrendition\", { rendition }));\n  });\n}\nfunction removeRendition(rendition) {\n  const renditionList = getPrivate(rendition).media.audioRenditions;\n  const track = getPrivate(rendition).track;\n  const renditionSet = getPrivate(track).renditionSet;\n  renditionSet.delete(rendition);\n  queueMicrotask(() => {\n    const track2 = getPrivate(rendition).track;\n    if (!track2.enabled) return;\n    renditionList.dispatchEvent(new RenditionEvent(\"removerendition\", { rendition }));\n  });\n}\nfunction selectedChanged(rendition) {\n  const renditionList = getPrivate(rendition).media.audioRenditions;\n  if (!renditionList || getPrivate(renditionList).changeRequested) return;\n  getPrivate(renditionList).changeRequested = true;\n  queueMicrotask(() => {\n    delete getPrivate(renditionList).changeRequested;\n    const track = getPrivate(rendition).track;\n    if (!track.enabled) return;\n    renditionList.dispatchEvent(new Event(\"change\"));\n  });\n}\nfunction getCurrentRenditions(renditionList) {\n  const media = getPrivate(renditionList).media;\n  return [...media.audioTracks].filter((track) => track.enabled).flatMap((track) => [...getPrivate(track).renditionSet]);\n}\nclass AudioRenditionList extends EventTarget {\n  #addRenditionCallback;\n  #removeRenditionCallback;\n  #changeCallback;\n  [Symbol.iterator]() {\n    return getCurrentRenditions(this).values();\n  }\n  get length() {\n    return getCurrentRenditions(this).length;\n  }\n  getRenditionById(id) {\n    return getCurrentRenditions(this).find((rendition) => `${rendition.id}` === `${id}`) ?? null;\n  }\n  get selectedIndex() {\n    return getCurrentRenditions(this).findIndex((rendition) => rendition.selected);\n  }\n  set selectedIndex(index) {\n    for (const [i, rendition] of getCurrentRenditions(this).entries()) {\n      rendition.selected = i === index;\n    }\n  }\n  get onaddrendition() {\n    return this.#addRenditionCallback;\n  }\n  set onaddrendition(callback) {\n    if (this.#addRenditionCallback) {\n      this.removeEventListener(\"addrendition\", this.#addRenditionCallback);\n      this.#addRenditionCallback = void 0;\n    }\n    if (typeof callback == \"function\") {\n      this.#addRenditionCallback = callback;\n      this.addEventListener(\"addrendition\", callback);\n    }\n  }\n  get onremoverendition() {\n    return this.#removeRenditionCallback;\n  }\n  set onremoverendition(callback) {\n    if (this.#removeRenditionCallback) {\n      this.removeEventListener(\"removerendition\", this.#removeRenditionCallback);\n      this.#removeRenditionCallback = void 0;\n    }\n    if (typeof callback == \"function\") {\n      this.#removeRenditionCallback = callback;\n      this.addEventListener(\"removerendition\", callback);\n    }\n  }\n  get onchange() {\n    return this.#changeCallback;\n  }\n  set onchange(callback) {\n    if (this.#changeCallback) {\n      this.removeEventListener(\"change\", this.#changeCallback);\n      this.#changeCallback = void 0;\n    }\n    if (typeof callback == \"function\") {\n      this.#changeCallback = callback;\n      this.addEventListener(\"change\", callback);\n    }\n  }\n}\nexport {\n  AudioRenditionList,\n  addRendition,\n  removeRendition,\n  selectedChanged\n};\n", "import { selectedChanged } from \"./audio-rendition-list.js\";\nclass AudioRendition {\n  src;\n  id;\n  bitrate;\n  codec;\n  #selected = false;\n  get selected() {\n    return this.#selected;\n  }\n  set selected(val) {\n    if (this.#selected === val) return;\n    this.#selected = val;\n    selectedChanged(this);\n  }\n}\nexport {\n  AudioRendition\n};\n", "import { TrackEvent } from \"./track-event.js\";\nimport { getPrivate } from \"./utils.js\";\nfunction addAudioTrack(media, track) {\n  const trackList = media.audioTracks;\n  getPrivate(track).media = media;\n  if (!getPrivate(track).renditionSet) {\n    getPrivate(track).renditionSet = /* @__PURE__ */ new Set();\n  }\n  const trackSet = getPrivate(trackList).trackSet;\n  trackSet.add(track);\n  const index = trackSet.size - 1;\n  if (!(index in AudioTrackList.prototype)) {\n    Object.defineProperty(AudioTrackList.prototype, index, {\n      get() {\n        return [...getPrivate(this).trackSet][index];\n      }\n    });\n  }\n  queueMicrotask(() => {\n    trackList.dispatchEvent(new TrackEvent(\"addtrack\", { track }));\n  });\n}\nfunction removeAudioTrack(track) {\n  const trackList = getPrivate(track).media?.audioTracks;\n  if (!trackList) return;\n  const trackSet = getPrivate(trackList).trackSet;\n  trackSet.delete(track);\n  queueMicrotask(() => {\n    trackList.dispatchEvent(new TrackEvent(\"removetrack\", { track }));\n  });\n}\nfunction enabledChanged(track) {\n  const trackList = getPrivate(track).media.audioTracks;\n  if (!trackList || getPrivate(trackList).changeRequested) return;\n  getPrivate(trackList).changeRequested = true;\n  queueMicrotask(() => {\n    delete getPrivate(trackList).changeRequested;\n    trackList.dispatchEvent(new Event(\"change\"));\n  });\n}\nclass AudioTrackList extends EventTarget {\n  #addTrackCallback;\n  #removeTrackCallback;\n  #changeCallback;\n  constructor() {\n    super();\n    getPrivate(this).trackSet = /* @__PURE__ */ new Set();\n  }\n  get #tracks() {\n    return getPrivate(this).trackSet;\n  }\n  [Symbol.iterator]() {\n    return this.#tracks.values();\n  }\n  get length() {\n    return this.#tracks.size;\n  }\n  getTrackById(id) {\n    return [...this.#tracks].find((track) => track.id === id) ?? null;\n  }\n  get onaddtrack() {\n    return this.#addTrackCallback;\n  }\n  set onaddtrack(callback) {\n    if (this.#addTrackCallback) {\n      this.removeEventListener(\"addtrack\", this.#addTrackCallback);\n      this.#addTrackCallback = void 0;\n    }\n    if (typeof callback == \"function\") {\n      this.#addTrackCallback = callback;\n      this.addEventListener(\"addtrack\", callback);\n    }\n  }\n  get onremovetrack() {\n    return this.#removeTrackCallback;\n  }\n  set onremovetrack(callback) {\n    if (this.#removeTrackCallback) {\n      this.removeEventListener(\"removetrack\", this.#removeTrackCallback);\n      this.#removeTrackCallback = void 0;\n    }\n    if (typeof callback == \"function\") {\n      this.#removeTrackCallback = callback;\n      this.addEventListener(\"removetrack\", callback);\n    }\n  }\n  get onchange() {\n    return this.#changeCallback;\n  }\n  set onchange(callback) {\n    if (this.#changeCallback) {\n      this.removeEventListener(\"change\", this.#changeCallback);\n      this.#changeCallback = void 0;\n    }\n    if (typeof callback == \"function\") {\n      this.#changeCallback = callback;\n      this.addEventListener(\"change\", callback);\n    }\n  }\n}\nexport {\n  AudioTrackList,\n  addAudioTrack,\n  enabledChanged,\n  removeAudioTrack\n};\n", "import { AudioRendition } from \"./audio-rendition.js\";\nimport { enabledChanged } from \"./audio-track-list.js\";\nimport { addRendition, removeRendition } from \"./audio-rendition-list.js\";\nconst AudioTrackKind = {\n  alternative: \"alternative\",\n  descriptions: \"descriptions\",\n  main: \"main\",\n  \"main-desc\": \"main-desc\",\n  translation: \"translation\",\n  commentary: \"commentary\"\n};\nclass AudioTrack {\n  id;\n  kind;\n  label = \"\";\n  language = \"\";\n  sourceBuffer;\n  #enabled = false;\n  addRendition(src, codec, bitrate) {\n    const rendition = new AudioRendition();\n    rendition.src = src;\n    rendition.codec = codec;\n    rendition.bitrate = bitrate;\n    addRendition(this, rendition);\n    return rendition;\n  }\n  removeRendition(rendition) {\n    removeRendition(rendition);\n  }\n  get enabled() {\n    return this.#enabled;\n  }\n  set enabled(val) {\n    if (this.#enabled === val) return;\n    this.#enabled = val;\n    enabledChanged(this);\n  }\n}\nexport {\n  AudioTrack,\n  AudioTrackKind\n};\n", "import { VideoTrack } from \"./video-track.js\";\nimport { VideoTrackList, addVideoTrack, removeVideoTrack } from \"./video-track-list.js\";\nimport { AudioTrack } from \"./audio-track.js\";\nimport { AudioTrackList, addAudioTrack, removeAudioTrack } from \"./audio-track-list.js\";\nimport { VideoRenditionList } from \"./video-rendition-list.js\";\nimport { AudioRenditionList } from \"./audio-rendition-list.js\";\nimport { getPrivate } from \"./utils.js\";\nconst nativeVideoTracksFn = getBaseMediaTracksFn(globalThis.HTMLMediaElement, \"video\");\nconst nativeAudioTracksFn = getBaseMediaTracksFn(globalThis.HTMLMediaElement, \"audio\");\nfunction MediaTracksMixin(MediaElementClass) {\n  if (!MediaElementClass?.prototype) return MediaElementClass;\n  const videoTracksFn = getBaseMediaTracksFn(MediaElementClass, \"video\");\n  if (!videoTracksFn || `${videoTracksFn}`.includes(\"[native code]\")) {\n    Object.defineProperty(MediaElementClass.prototype, \"videoTracks\", {\n      get() {\n        return getVideoTracks(this);\n      }\n    });\n  }\n  const audioTracksFn = getBaseMediaTracksFn(MediaElementClass, \"audio\");\n  if (!audioTracksFn || `${audioTracksFn}`.includes(\"[native code]\")) {\n    Object.defineProperty(MediaElementClass.prototype, \"audioTracks\", {\n      get() {\n        return getAudioTracks(this);\n      }\n    });\n  }\n  if (!(\"addVideoTrack\" in MediaElementClass.prototype)) {\n    MediaElementClass.prototype.addVideoTrack = function(kind, label = \"\", language = \"\") {\n      const track = new VideoTrack();\n      track.kind = kind;\n      track.label = label;\n      track.language = language;\n      addVideoTrack(this, track);\n      return track;\n    };\n  }\n  if (!(\"removeVideoTrack\" in MediaElementClass.prototype)) {\n    MediaElementClass.prototype.removeVideoTrack = removeVideoTrack;\n  }\n  if (!(\"addAudioTrack\" in MediaElementClass.prototype)) {\n    MediaElementClass.prototype.addAudioTrack = function(kind, label = \"\", language = \"\") {\n      const track = new AudioTrack();\n      track.kind = kind;\n      track.label = label;\n      track.language = language;\n      addAudioTrack(this, track);\n      return track;\n    };\n  }\n  if (!(\"removeAudioTrack\" in MediaElementClass.prototype)) {\n    MediaElementClass.prototype.removeAudioTrack = removeAudioTrack;\n  }\n  if (!(\"videoRenditions\" in MediaElementClass.prototype)) {\n    Object.defineProperty(MediaElementClass.prototype, \"videoRenditions\", {\n      get() {\n        return initVideoRenditions(this);\n      }\n    });\n  }\n  const initVideoRenditions = (media) => {\n    let renditions = getPrivate(media).videoRenditions;\n    if (!renditions) {\n      renditions = new VideoRenditionList();\n      getPrivate(renditions).media = media;\n      getPrivate(media).videoRenditions = renditions;\n    }\n    return renditions;\n  };\n  if (!(\"audioRenditions\" in MediaElementClass.prototype)) {\n    Object.defineProperty(MediaElementClass.prototype, \"audioRenditions\", {\n      get() {\n        return initAudioRenditions(this);\n      }\n    });\n  }\n  const initAudioRenditions = (media) => {\n    let renditions = getPrivate(media).audioRenditions;\n    if (!renditions) {\n      renditions = new AudioRenditionList();\n      getPrivate(renditions).media = media;\n      getPrivate(media).audioRenditions = renditions;\n    }\n    return renditions;\n  };\n  return MediaElementClass;\n}\nfunction getBaseMediaTracksFn(MediaElementClass, type) {\n  if (MediaElementClass?.prototype) {\n    return Object.getOwnPropertyDescriptor(MediaElementClass.prototype, `${type}Tracks`)?.get;\n  }\n}\nfunction getVideoTracks(media) {\n  let tracks = getPrivate(media).videoTracks;\n  if (!tracks) {\n    tracks = new VideoTrackList();\n    getPrivate(media).videoTracks = tracks;\n    if (nativeVideoTracksFn) {\n      const nativeTracks = nativeVideoTracksFn.call(media.nativeEl ?? media);\n      for (const nativeTrack of nativeTracks) {\n        addVideoTrack(media, nativeTrack);\n      }\n      nativeTracks.addEventListener(\"change\", () => {\n        tracks.dispatchEvent(new Event(\"change\"));\n      });\n      nativeTracks.addEventListener(\"addtrack\", (event) => {\n        if ([...tracks].some((t) => t instanceof VideoTrack)) {\n          for (const nativeTrack of nativeTracks) {\n            removeVideoTrack(nativeTrack);\n          }\n          return;\n        }\n        addVideoTrack(media, event.track);\n      });\n      nativeTracks.addEventListener(\"removetrack\", (event) => {\n        removeVideoTrack(event.track);\n      });\n    }\n  }\n  return tracks;\n}\nfunction getAudioTracks(media) {\n  let tracks = getPrivate(media).audioTracks;\n  if (!tracks) {\n    tracks = new AudioTrackList();\n    getPrivate(media).audioTracks = tracks;\n    if (nativeAudioTracksFn) {\n      const nativeTracks = nativeAudioTracksFn.call(media.nativeEl ?? media);\n      for (const nativeTrack of nativeTracks) {\n        addAudioTrack(media, nativeTrack);\n      }\n      nativeTracks.addEventListener(\"change\", () => {\n        tracks.dispatchEvent(new Event(\"change\"));\n      });\n      nativeTracks.addEventListener(\"addtrack\", (event) => {\n        if ([...tracks].some((t) => t instanceof AudioTrack)) {\n          for (const nativeTrack of nativeTracks) {\n            removeAudioTrack(nativeTrack);\n          }\n          return;\n        }\n        addAudioTrack(media, event.track);\n      });\n      nativeTracks.addEventListener(\"removetrack\", (event) => {\n        removeAudioTrack(event.track);\n      });\n    }\n  }\n  return tracks;\n}\nexport {\n  MediaTracksMixin\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar __privateSet = (obj, member, value, setter) => {\n  __accessCheck(obj, member, \"write to private field\");\n  setter ? setter.call(obj, value) : member.set(obj, value);\n  return value;\n};\nvar _parts, _processor, _items, _value, _element, _attributeName, _namespaceURI, _list, list_get, _parentNode, _nodes;\nimport { globalThis } from \"../utils/server-safe-globals.js\";\nconst ELEMENT = 1;\nconst STRING = 0;\nconst PART = 1;\nconst defaultProcessor = {\n  processCallback(instance, parts, state) {\n    if (!state)\n      return;\n    for (const [expression, part] of parts) {\n      if (expression in state) {\n        const value = state[expression];\n        if (typeof value === \"boolean\" && part instanceof AttrPart && typeof part.element[part.attributeName] === \"boolean\") {\n          part.booleanValue = value;\n        } else if (typeof value === \"function\" && part instanceof AttrPart) {\n          part.element[part.attributeName] = value;\n        } else {\n          part.value = value;\n        }\n      }\n    }\n  }\n};\nclass TemplateInstance extends globalThis.DocumentFragment {\n  constructor(template, state, processor = defaultProcessor) {\n    var _a;\n    super();\n    __privateAdd(this, _parts, void 0);\n    __privateAdd(this, _processor, void 0);\n    this.append(template.content.cloneNode(true));\n    __privateSet(this, _parts, parse(this));\n    __privateSet(this, _processor, processor);\n    (_a = processor.createCallback) == null ? void 0 : _a.call(processor, this, __privateGet(this, _parts), state);\n    processor.processCallback(this, __privateGet(this, _parts), state);\n  }\n  update(state) {\n    __privateGet(this, _processor).processCallback(this, __privateGet(this, _parts), state);\n  }\n}\n_parts = new WeakMap();\n_processor = new WeakMap();\nconst parse = (element, parts = []) => {\n  let type, value;\n  for (const attr of element.attributes || []) {\n    if (attr.value.includes(\"{{\")) {\n      const list = new AttrPartList();\n      for ([type, value] of tokenize(attr.value)) {\n        if (!type)\n          list.append(value);\n        else {\n          const part = new AttrPart(element, attr.name, attr.namespaceURI);\n          list.append(part);\n          parts.push([value, part]);\n        }\n      }\n      attr.value = list.toString();\n    }\n  }\n  for (const node of element.childNodes) {\n    if (node.nodeType === ELEMENT && !(node instanceof HTMLTemplateElement)) {\n      parse(node, parts);\n    } else {\n      const data = node.data;\n      if (node.nodeType === ELEMENT || data.includes(\"{{\")) {\n        const items = [];\n        if (data) {\n          for ([type, value] of tokenize(data))\n            if (!type)\n              items.push(new Text(value));\n            else {\n              const part = new ChildNodePart(element);\n              items.push(part);\n              parts.push([value, part]);\n            }\n        } else if (node instanceof HTMLTemplateElement) {\n          const part = new InnerTemplatePart(element, node);\n          items.push(part);\n          parts.push([part.expression, part]);\n        }\n        node.replaceWith(\n          ...items.flatMap((part) => part.replacementNodes || [part])\n        );\n      }\n    }\n  }\n  return parts;\n};\nconst mem = {};\nconst tokenize = (text) => {\n  let value = \"\", open = 0, tokens = mem[text], i = 0, c;\n  if (tokens)\n    return tokens;\n  else\n    tokens = [];\n  for (; c = text[i]; i++) {\n    if (c === \"{\" && text[i + 1] === \"{\" && text[i - 1] !== \"\\\\\" && text[i + 2] && ++open == 1) {\n      if (value)\n        tokens.push([STRING, value]);\n      value = \"\";\n      i++;\n    } else if (c === \"}\" && text[i + 1] === \"}\" && text[i - 1] !== \"\\\\\" && !--open) {\n      tokens.push([PART, value.trim()]);\n      value = \"\";\n      i++;\n    } else\n      value += c || \"\";\n  }\n  if (value)\n    tokens.push([STRING, (open > 0 ? \"{{\" : \"\") + value]);\n  return mem[text] = tokens;\n};\nconst FRAGMENT = 11;\nclass Part {\n  get value() {\n    return \"\";\n  }\n  set value(val) {\n  }\n  toString() {\n    return this.value;\n  }\n}\nconst attrPartToList = /* @__PURE__ */ new WeakMap();\nclass AttrPartList {\n  constructor() {\n    __privateAdd(this, _items, []);\n  }\n  [Symbol.iterator]() {\n    return __privateGet(this, _items).values();\n  }\n  get length() {\n    return __privateGet(this, _items).length;\n  }\n  item(index) {\n    return __privateGet(this, _items)[index];\n  }\n  append(...items) {\n    for (const item of items) {\n      if (item instanceof AttrPart) {\n        attrPartToList.set(item, this);\n      }\n      __privateGet(this, _items).push(item);\n    }\n  }\n  toString() {\n    return __privateGet(this, _items).join(\"\");\n  }\n}\n_items = new WeakMap();\nclass AttrPart extends Part {\n  constructor(element, attributeName, namespaceURI) {\n    super();\n    __privateAdd(this, _list);\n    __privateAdd(this, _value, \"\");\n    __privateAdd(this, _element, void 0);\n    __privateAdd(this, _attributeName, void 0);\n    __privateAdd(this, _namespaceURI, void 0);\n    __privateSet(this, _element, element);\n    __privateSet(this, _attributeName, attributeName);\n    __privateSet(this, _namespaceURI, namespaceURI);\n  }\n  get attributeName() {\n    return __privateGet(this, _attributeName);\n  }\n  get attributeNamespace() {\n    return __privateGet(this, _namespaceURI);\n  }\n  get element() {\n    return __privateGet(this, _element);\n  }\n  get value() {\n    return __privateGet(this, _value);\n  }\n  set value(newValue) {\n    if (__privateGet(this, _value) === newValue)\n      return;\n    __privateSet(this, _value, newValue);\n    if (!__privateGet(this, _list, list_get) || __privateGet(this, _list, list_get).length === 1) {\n      if (newValue == null) {\n        __privateGet(this, _element).removeAttributeNS(\n          __privateGet(this, _namespaceURI),\n          __privateGet(this, _attributeName)\n        );\n      } else {\n        __privateGet(this, _element).setAttributeNS(\n          __privateGet(this, _namespaceURI),\n          __privateGet(this, _attributeName),\n          newValue\n        );\n      }\n    } else {\n      __privateGet(this, _element).setAttributeNS(\n        __privateGet(this, _namespaceURI),\n        __privateGet(this, _attributeName),\n        __privateGet(this, _list, list_get).toString()\n      );\n    }\n  }\n  get booleanValue() {\n    return __privateGet(this, _element).hasAttributeNS(\n      __privateGet(this, _namespaceURI),\n      __privateGet(this, _attributeName)\n    );\n  }\n  set booleanValue(value) {\n    if (!__privateGet(this, _list, list_get) || __privateGet(this, _list, list_get).length === 1)\n      this.value = value ? \"\" : null;\n    else\n      throw new DOMException(\"Value is not fully templatized\");\n  }\n}\n_value = new WeakMap();\n_element = new WeakMap();\n_attributeName = new WeakMap();\n_namespaceURI = new WeakMap();\n_list = new WeakSet();\nlist_get = function() {\n  return attrPartToList.get(this);\n};\nclass ChildNodePart extends Part {\n  constructor(parentNode, nodes) {\n    super();\n    __privateAdd(this, _parentNode, void 0);\n    __privateAdd(this, _nodes, void 0);\n    __privateSet(this, _parentNode, parentNode);\n    __privateSet(this, _nodes, nodes ? [...nodes] : [new Text()]);\n  }\n  get replacementNodes() {\n    return __privateGet(this, _nodes);\n  }\n  get parentNode() {\n    return __privateGet(this, _parentNode);\n  }\n  get nextSibling() {\n    return __privateGet(this, _nodes)[__privateGet(this, _nodes).length - 1].nextSibling;\n  }\n  get previousSibling() {\n    return __privateGet(this, _nodes)[0].previousSibling;\n  }\n  // FIXME: not sure why do we need string serialization here? Just because parent class has type DOMString?\n  get value() {\n    return __privateGet(this, _nodes).map((node) => node.textContent).join(\"\");\n  }\n  set value(newValue) {\n    this.replace(newValue);\n  }\n  replace(...nodes) {\n    const normalisedNodes = nodes.flat().flatMap(\n      (node) => node == null ? [new Text()] : node.forEach ? [...node] : node.nodeType === FRAGMENT ? [...node.childNodes] : node.nodeType ? [node] : [new Text(node)]\n    );\n    if (!normalisedNodes.length)\n      normalisedNodes.push(new Text());\n    __privateSet(this, _nodes, swapdom(\n      __privateGet(this, _nodes)[0].parentNode,\n      __privateGet(this, _nodes),\n      normalisedNodes,\n      this.nextSibling\n    ));\n  }\n}\n_parentNode = new WeakMap();\n_nodes = new WeakMap();\nclass InnerTemplatePart extends ChildNodePart {\n  constructor(parentNode, template) {\n    const directive = template.getAttribute(\"directive\") || template.getAttribute(\"type\");\n    let expression = template.getAttribute(\"expression\") || template.getAttribute(directive) || \"\";\n    if (expression.startsWith(\"{{\"))\n      expression = expression.trim().slice(2, -2).trim();\n    super(parentNode);\n    this.expression = expression;\n    this.template = template;\n    this.directive = directive;\n  }\n}\nfunction swapdom(parent, a, b, end = null) {\n  let i = 0, cur, next, bi, n = b.length, m = a.length;\n  while (i < n && i < m && a[i] == b[i])\n    i++;\n  while (i < n && i < m && b[n - 1] == a[m - 1])\n    end = b[--m, --n];\n  if (i == m)\n    while (i < n)\n      parent.insertBefore(b[i++], end);\n  if (i == n)\n    while (i < m)\n      parent.removeChild(a[i++]);\n  else {\n    cur = a[i];\n    while (i < n) {\n      bi = b[i++], next = cur ? cur.nextSibling : end;\n      if (cur == bi)\n        cur = next;\n      else if (i < n && b[i] == next)\n        parent.replaceChild(bi, cur), cur = next;\n      else\n        parent.insertBefore(bi, cur);\n    }\n    while (cur != end)\n      next = cur.nextSibling, parent.removeChild(cur), cur = next;\n  }\n  return b;\n}\nexport {\n  AttrPart,\n  AttrPartList,\n  ChildNodePart,\n  InnerTemplatePart,\n  Part,\n  TemplateInstance,\n  defaultProcessor,\n  parse,\n  tokenize\n};\n", "import {\n  AttrPart,\n  InnerTemplatePart,\n  TemplateInstance\n} from \"./template-parts.js\";\nimport { isNumericString } from \"./utils.js\";\nconst pipeModifiers = {\n  string: (value) => String(value)\n};\nclass PartialTemplate {\n  constructor(template) {\n    this.template = template;\n    this.state = void 0;\n  }\n}\nconst templates = /* @__PURE__ */ new WeakMap();\nconst templateInstances = /* @__PURE__ */ new WeakMap();\nconst Directives = {\n  partial: (part, state) => {\n    state[part.expression] = new PartialTemplate(part.template);\n  },\n  if: (part, state) => {\n    var _a;\n    if (evaluateExpression(part.expression, state)) {\n      if (templates.get(part) !== part.template) {\n        templates.set(part, part.template);\n        const tpl = new TemplateInstance(part.template, state, processor);\n        part.replace(tpl);\n        templateInstances.set(part, tpl);\n      } else {\n        (_a = templateInstances.get(part)) == null ? void 0 : _a.update(state);\n      }\n    } else {\n      part.replace(\"\");\n      templates.delete(part);\n      templateInstances.delete(part);\n    }\n  }\n};\nconst DirectiveNames = Object.keys(Directives);\nconst processor = {\n  processCallback(instance, parts, state) {\n    var _a, _b;\n    if (!state)\n      return;\n    for (const [expression, part] of parts) {\n      if (part instanceof InnerTemplatePart) {\n        if (!part.directive) {\n          const directive = DirectiveNames.find(\n            (n) => part.template.hasAttribute(n)\n          );\n          if (directive) {\n            part.directive = directive;\n            part.expression = part.template.getAttribute(directive);\n          }\n        }\n        (_a = Directives[part.directive]) == null ? void 0 : _a.call(Directives, part, state);\n        continue;\n      }\n      let value = evaluateExpression(expression, state);\n      if (value instanceof PartialTemplate) {\n        if (templates.get(part) !== value.template) {\n          templates.set(part, value.template);\n          value = new TemplateInstance(value.template, value.state, processor);\n          part.value = value;\n          templateInstances.set(part, value);\n        } else {\n          (_b = templateInstances.get(part)) == null ? void 0 : _b.update(value.state);\n        }\n        continue;\n      }\n      if (value) {\n        if (part instanceof AttrPart) {\n          if (part.attributeName.startsWith(\"aria-\")) {\n            value = String(value);\n          }\n        }\n        if (part instanceof AttrPart) {\n          if (typeof value === \"boolean\") {\n            part.booleanValue = value;\n          } else if (typeof value === \"function\") {\n            part.element[part.attributeName] = value;\n          } else {\n            part.value = value;\n          }\n        } else {\n          part.value = value;\n          templates.delete(part);\n          templateInstances.delete(part);\n        }\n      } else {\n        if (part instanceof AttrPart) {\n          part.value = void 0;\n        } else {\n          part.value = void 0;\n          templates.delete(part);\n          templateInstances.delete(part);\n        }\n      }\n    }\n  }\n};\nconst operators = {\n  \"!\": (a) => !a,\n  \"!!\": (a) => !!a,\n  \"==\": (a, b) => a == b,\n  \"!=\": (a, b) => a != b,\n  \">\": (a, b) => a > b,\n  \">=\": (a, b) => a >= b,\n  \"<\": (a, b) => a < b,\n  \"<=\": (a, b) => a <= b,\n  \"??\": (a, b) => a != null ? a : b,\n  \"|\": (a, b) => {\n    var _a;\n    return (_a = pipeModifiers[b]) == null ? void 0 : _a.call(pipeModifiers, a);\n  }\n};\nfunction tokenizeExpression(expr) {\n  return tokenize(expr, {\n    boolean: /true|false/,\n    number: /-?\\d+\\.?\\d*/,\n    string: /([\"'])((?:\\\\.|[^\\\\])*?)\\1/,\n    operator: /[!=><][=!]?|\\?\\?|\\|/,\n    ws: /\\s+/,\n    param: /[$a-z_][$\\w]*/i\n  }).filter(({ type }) => type !== \"ws\");\n}\nfunction evaluateExpression(expr, state = {}) {\n  var _a, _b, _c, _d, _e, _f, _g;\n  const tokens = tokenizeExpression(expr);\n  if (tokens.length === 0 || tokens.some(({ type }) => !type)) {\n    return invalidExpression(expr);\n  }\n  if (((_a = tokens[0]) == null ? void 0 : _a.token) === \">\") {\n    const partial = state[(_b = tokens[1]) == null ? void 0 : _b.token];\n    if (!partial) {\n      return invalidExpression(expr);\n    }\n    const partialState = { ...state };\n    partial.state = partialState;\n    const args = tokens.slice(2);\n    for (let i = 0; i < args.length; i += 3) {\n      const name = (_c = args[i]) == null ? void 0 : _c.token;\n      const operator = (_d = args[i + 1]) == null ? void 0 : _d.token;\n      const value = (_e = args[i + 2]) == null ? void 0 : _e.token;\n      if (name && operator === \"=\") {\n        partialState[name] = getParamValue(value, state);\n      }\n    }\n    return partial;\n  }\n  if (tokens.length === 1) {\n    if (!isValidParam(tokens[0])) {\n      return invalidExpression(expr);\n    }\n    return getParamValue(tokens[0].token, state);\n  }\n  if (tokens.length === 2) {\n    const operator = (_f = tokens[0]) == null ? void 0 : _f.token;\n    const run = operators[operator];\n    if (!run || !isValidParam(tokens[1])) {\n      return invalidExpression(expr);\n    }\n    const a = getParamValue(tokens[1].token, state);\n    return run(a);\n  }\n  if (tokens.length === 3) {\n    const operator = (_g = tokens[1]) == null ? void 0 : _g.token;\n    const run = operators[operator];\n    if (!run || !isValidParam(tokens[0]) || !isValidParam(tokens[2])) {\n      return invalidExpression(expr);\n    }\n    const a = getParamValue(tokens[0].token, state);\n    if (operator === \"|\") {\n      return run(a, tokens[2].token);\n    }\n    const b = getParamValue(tokens[2].token, state);\n    return run(a, b);\n  }\n}\nfunction invalidExpression(expr) {\n  console.warn(`Warning: invalid expression \\`${expr}\\``);\n  return false;\n}\nfunction isValidParam({ type }) {\n  return [\"number\", \"boolean\", \"string\", \"param\"].includes(type);\n}\nfunction getParamValue(raw, state) {\n  const firstChar = raw[0];\n  const lastChar = raw.slice(-1);\n  if (raw === \"true\" || raw === \"false\") {\n    return raw === \"true\";\n  }\n  if (firstChar === lastChar && [`'`, `\"`].includes(firstChar)) {\n    return raw.slice(1, -1);\n  }\n  if (isNumericString(raw)) {\n    return parseFloat(raw);\n  }\n  return state[raw];\n}\nfunction tokenize(str, parsers) {\n  let len, match, token;\n  const tokens = [];\n  while (str) {\n    token = null;\n    len = str.length;\n    for (const key in parsers) {\n      match = parsers[key].exec(str);\n      if (match && match.index < len) {\n        token = {\n          token: match[0],\n          type: key,\n          matches: match.slice(1)\n        };\n        len = match.index;\n      }\n    }\n    if (len) {\n      tokens.push({\n        token: str.substr(0, len),\n        type: void 0\n      });\n    }\n    if (token) {\n      tokens.push(token);\n    }\n    str = str.substr(len + (token ? token.token.length : 0));\n  }\n  return tokens;\n}\nexport {\n  evaluateExpression,\n  getParamValue,\n  processor,\n  tokenizeExpression\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar __privateSet = (obj, member, value, setter) => {\n  __accessCheck(obj, member, \"write to private field\");\n  setter ? setter.call(obj, value) : member.set(obj, value);\n  return value;\n};\nvar __privateMethod = (obj, member, method) => {\n  __accessCheck(obj, member, \"access private method\");\n  return method;\n};\nvar _template, _prevTemplate, _prevTemplateId, _upgradeProperty, upgradeProperty_fn, _updateTemplate, updateTemplate_fn;\nimport { MediaStateChangeEvents } from \"./constants.js\";\nimport { getOrInsertCSSRule } from \"./utils/element-utils.js\";\nimport { globalThis, document } from \"./utils/server-safe-globals.js\";\nimport { TemplateInstance } from \"./utils/template-parts.js\";\nimport { processor } from \"./utils/template-processor.js\";\nimport { camelCase, isNumericString } from \"./utils/utils.js\";\nexport * from \"./utils/template-parts.js\";\nconst observedMediaAttributes = {\n  mediatargetlivewindow: \"targetlivewindow\",\n  mediastreamtype: \"streamtype\"\n};\nconst prependTemplate = document.createElement(\"template\");\nprependTemplate.innerHTML = /*html*/\n`\n  <style>\n    :host {\n      display: inline-block;\n      line-height: 0;\n\n      /* Hide theme element until the breakpoints are available to avoid flicker. */\n      visibility: hidden;\n    }\n\n    media-controller {\n      width: 100%;\n      height: 100%;\n    }\n\n    media-captions-button:not([mediasubtitleslist]),\n    media-captions-menu:not([mediasubtitleslist]),\n    media-captions-menu-button:not([mediasubtitleslist]),\n    media-audio-track-menu[mediaaudiotrackunavailable],\n    media-audio-track-menu-button[mediaaudiotrackunavailable],\n    media-rendition-menu[mediarenditionunavailable],\n    media-rendition-menu-button[mediarenditionunavailable],\n    media-volume-range[mediavolumeunavailable],\n    media-airplay-button[mediaairplayunavailable],\n    media-fullscreen-button[mediafullscreenunavailable],\n    media-cast-button[mediacastunavailable],\n    media-pip-button[mediapipunavailable] {\n      display: none;\n    }\n  </style>\n`;\nclass MediaThemeElement extends globalThis.HTMLElement {\n  constructor() {\n    super();\n    __privateAdd(this, _upgradeProperty);\n    __privateAdd(this, _updateTemplate);\n    __privateAdd(this, _template, void 0);\n    __privateAdd(this, _prevTemplate, void 0);\n    __privateAdd(this, _prevTemplateId, void 0);\n    if (this.shadowRoot) {\n      this.renderRoot = this.shadowRoot;\n    } else {\n      this.renderRoot = this.attachShadow({ mode: \"open\" });\n      this.createRenderer();\n    }\n    const observer = new MutationObserver((mutationList) => {\n      var _a;\n      if (this.mediaController && !((_a = this.mediaController) == null ? void 0 : _a.breakpointsComputed))\n        return;\n      if (mutationList.some((mutation) => {\n        const target = mutation.target;\n        if (target === this)\n          return true;\n        if (target.localName !== \"media-controller\")\n          return false;\n        if (observedMediaAttributes[mutation.attributeName])\n          return true;\n        if (mutation.attributeName.startsWith(\"breakpoint\"))\n          return true;\n        return false;\n      })) {\n        this.render();\n      }\n    });\n    observer.observe(this, { attributes: true });\n    observer.observe(this.renderRoot, {\n      attributes: true,\n      subtree: true\n    });\n    this.addEventListener(\n      MediaStateChangeEvents.BREAKPOINTS_COMPUTED,\n      this.render\n    );\n    __privateMethod(this, _upgradeProperty, upgradeProperty_fn).call(this, \"template\");\n  }\n  /** @type {HTMLElement & { breakpointsComputed?: boolean }} */\n  get mediaController() {\n    return this.renderRoot.querySelector(\"media-controller\");\n  }\n  get template() {\n    var _a;\n    return (_a = __privateGet(this, _template)) != null ? _a : this.constructor.template;\n  }\n  set template(element) {\n    __privateSet(this, _prevTemplateId, null);\n    __privateSet(this, _template, element);\n    this.createRenderer();\n  }\n  get props() {\n    var _a, _b, _c;\n    const observedAttributes = [\n      ...Array.from((_b = (_a = this.mediaController) == null ? void 0 : _a.attributes) != null ? _b : []).filter(\n        ({ name }) => {\n          return observedMediaAttributes[name] || name.startsWith(\"breakpoint\");\n        }\n      ),\n      ...Array.from(this.attributes)\n    ];\n    const props = {};\n    for (const attr of observedAttributes) {\n      const name = (_c = observedMediaAttributes[attr.name]) != null ? _c : camelCase(attr.name);\n      let { value } = attr;\n      if (value != null) {\n        if (isNumericString(value)) {\n          value = parseFloat(value);\n        }\n        props[name] = value === \"\" ? true : value;\n      } else {\n        props[name] = false;\n      }\n    }\n    return props;\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    if (attrName === \"template\" && oldValue != newValue) {\n      __privateMethod(this, _updateTemplate, updateTemplate_fn).call(this);\n    }\n  }\n  connectedCallback() {\n    __privateMethod(this, _updateTemplate, updateTemplate_fn).call(this);\n  }\n  createRenderer() {\n    if (this.template && this.template !== __privateGet(this, _prevTemplate)) {\n      __privateSet(this, _prevTemplate, this.template);\n      this.renderer = new TemplateInstance(\n        this.template,\n        this.props,\n        // @ts-ignore\n        this.constructor.processor\n      );\n      this.renderRoot.textContent = \"\";\n      this.renderRoot.append(\n        prependTemplate.content.cloneNode(true),\n        this.renderer\n      );\n    }\n  }\n  render() {\n    var _a;\n    (_a = this.renderer) == null ? void 0 : _a.update(this.props);\n    if (this.renderRoot.isConnected) {\n      const { style } = getOrInsertCSSRule(this.renderRoot, \":host\");\n      if (style.visibility === \"hidden\") {\n        style.removeProperty(\"visibility\");\n      }\n    }\n  }\n}\n_template = new WeakMap();\n_prevTemplate = new WeakMap();\n_prevTemplateId = new WeakMap();\n_upgradeProperty = new WeakSet();\nupgradeProperty_fn = function(prop) {\n  if (Object.prototype.hasOwnProperty.call(this, prop)) {\n    const value = this[prop];\n    delete this[prop];\n    this[prop] = value;\n  }\n};\n_updateTemplate = new WeakSet();\nupdateTemplate_fn = function() {\n  var _a;\n  const templateId = this.getAttribute(\"template\");\n  if (!templateId || templateId === __privateGet(this, _prevTemplateId))\n    return;\n  const rootNode = this.getRootNode();\n  const template = (_a = rootNode == null ? void 0 : rootNode.getElementById) == null ? void 0 : _a.call(rootNode, templateId);\n  if (template) {\n    __privateSet(this, _prevTemplateId, templateId);\n    __privateSet(this, _template, template);\n    this.createRenderer();\n    return;\n  }\n  if (isValidUrl(templateId)) {\n    __privateSet(this, _prevTemplateId, templateId);\n    request(templateId).then((data) => {\n      const template2 = document.createElement(\"template\");\n      template2.innerHTML = data;\n      __privateSet(this, _template, template2);\n      this.createRenderer();\n    }).catch(console.error);\n  }\n};\nMediaThemeElement.observedAttributes = [\"template\"];\nMediaThemeElement.processor = processor;\nfunction isValidUrl(url) {\n  if (!/^(\\/|\\.\\/|https?:\\/\\/)/.test(url))\n    return false;\n  const base = /^https?:\\/\\//.test(url) ? void 0 : location.origin;\n  try {\n    new URL(url, base);\n  } catch (e) {\n    return false;\n  }\n  return true;\n}\nasync function request(resource) {\n  const response = await fetch(resource);\n  if (response.status !== 200) {\n    throw new Error(\n      `Failed to load resource: the server responded with a status of ${response.status}`\n    );\n  }\n  return response.text();\n}\nif (!globalThis.customElements.get(\"media-theme\")) {\n  globalThis.customElements.define(\"media-theme\", MediaThemeElement);\n}\nexport {\n  MediaThemeElement\n};\n", "function computePosition({\n  anchor,\n  floating,\n  placement\n}) {\n  const rects = getElementRects({ anchor, floating });\n  const { x, y } = computeCoordsFromPlacement(rects, placement);\n  return { x, y };\n}\nfunction getElementRects({\n  anchor,\n  floating\n}) {\n  return {\n    anchor: getRectRelativeToOffsetParent(anchor, floating.offsetParent),\n    floating: {\n      x: 0,\n      y: 0,\n      width: floating.offsetWidth,\n      height: floating.offsetHeight\n    }\n  };\n}\nfunction getRectRelativeToOffsetParent(element, offsetParent) {\n  var _a;\n  const rect = element.getBoundingClientRect();\n  const offsetRect = (_a = offsetParent == null ? void 0 : offsetParent.getBoundingClientRect()) != null ? _a : { x: 0, y: 0 };\n  return {\n    x: rect.x - offsetRect.x,\n    y: rect.y - offsetRect.y,\n    width: rect.width,\n    height: rect.height\n  };\n}\nfunction computeCoordsFromPlacement({ anchor, floating }, placement) {\n  const alignmentAxis = getSideAxis(placement) === \"x\" ? \"y\" : \"x\";\n  const alignLength = alignmentAxis === \"y\" ? \"height\" : \"width\";\n  const side = getSide(placement);\n  const commonX = anchor.x + anchor.width / 2 - floating.width / 2;\n  const commonY = anchor.y + anchor.height / 2 - floating.height / 2;\n  const commonAlign = anchor[alignLength] / 2 - floating[alignLength] / 2;\n  let coords;\n  switch (side) {\n    case \"top\":\n      coords = { x: commonX, y: anchor.y - floating.height };\n      break;\n    case \"bottom\":\n      coords = { x: commonX, y: anchor.y + anchor.height };\n      break;\n    case \"right\":\n      coords = { x: anchor.x + anchor.width, y: commonY };\n      break;\n    case \"left\":\n      coords = { x: anchor.x - floating.width, y: commonY };\n      break;\n    default:\n      coords = { x: anchor.x, y: anchor.y };\n  }\n  switch (placement.split(\"-\")[1]) {\n    case \"start\":\n      coords[alignmentAxis] -= commonAlign;\n      break;\n    case \"end\":\n      coords[alignmentAxis] += commonAlign;\n      break;\n  }\n  return coords;\n}\nfunction getSide(placement) {\n  return placement.split(\"-\")[0];\n}\nfunction getSideAxis(placement) {\n  return [\"top\", \"bottom\"].includes(getSide(placement)) ? \"y\" : \"x\";\n}\nexport {\n  computePosition\n};\n", "class InvokeEvent extends Event {\n  /**\n   * @param init - The event options.\n   */\n  constructor({ action = \"auto\", relatedTarget, ...options }) {\n    super(\"invoke\", options);\n    this.action = action;\n    this.relatedTarget = relatedTarget;\n  }\n}\nclass ToggleEvent extends Event {\n  /**\n   * @param init - The event options.\n   */\n  constructor({ newState, oldState, ...options }) {\n    super(\"toggle\", options);\n    this.newState = newState;\n    this.oldState = oldState;\n  }\n}\nexport {\n  InvokeEvent,\n  ToggleEvent\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar __privateSet = (obj, member, value, setter) => {\n  __accessCheck(obj, member, \"write to private field\");\n  setter ? setter.call(obj, value) : member.set(obj, value);\n  return value;\n};\nvar __privateMethod = (obj, member, method) => {\n  __accessCheck(obj, member, \"access private method\");\n  return method;\n};\nvar _mediaController, _previouslyFocused, _invokerElement, _previousItems, _mutationObserver, _isPopover, _cssRule, _handleSlotChange, handleSlotChange_fn, _handleMenuItems, _updateLayoutStyle, updateLayoutStyle_fn, _handleInvoke, handleInvoke_fn, _handleOpen, handleOpen_fn, _handleClosed, handleClosed_fn, _handleBoundsResize, _handleMenuResize, _positionMenu, positionMenu_fn, _resizeMenu, resizeMenu_fn, _handleClick, handleClick_fn, _backButtonElement, backButtonElement_get, _handleToggle, handleToggle_fn, _checkSubmenuHasExpanded, checkSubmenuHasExpanded_fn, _handleFocusOut, handleFocusOut_fn, _handleKeyDown, handleKeyDown_fn, _getItem, getItem_fn, _getTabItem, getTabItem_fn, _setTabItem, setTabItem_fn, _selectItem, selectItem_fn;\nimport { MediaStateReceiverAttributes } from \"../constants.js\";\nimport { globalThis, document } from \"../utils/server-safe-globals.js\";\nimport { computePosition } from \"../utils/anchor-utils.js\";\nimport { observeResize, unobserveResize } from \"../utils/resize-observer.js\";\nimport { ToggleEvent, InvokeEvent } from \"../utils/events.js\";\nimport {\n  getActiveElement,\n  containsComposedNode,\n  closestComposedNode,\n  insertCSSRule,\n  getMediaController,\n  getAttributeMediaController,\n  getDocumentOrShadowRoot\n} from \"../utils/element-utils.js\";\nfunction createMenuItem({\n  type,\n  text,\n  value,\n  checked\n}) {\n  const item = document.createElement(\n    \"media-chrome-menu-item\"\n  );\n  item.type = type != null ? type : \"\";\n  item.part.add(\"menu-item\");\n  if (type)\n    item.part.add(type);\n  item.value = value;\n  item.checked = checked;\n  const label = document.createElement(\"span\");\n  label.textContent = text;\n  item.append(label);\n  return item;\n}\nfunction createIndicator(el, name) {\n  let customIndicator = el.querySelector(`:scope > [slot=\"${name}\"]`);\n  if ((customIndicator == null ? void 0 : customIndicator.nodeName) == \"SLOT\")\n    customIndicator = customIndicator.assignedElements({ flatten: true })[0];\n  if (customIndicator) {\n    customIndicator = customIndicator.cloneNode(true);\n    return customIndicator;\n  }\n  const fallbackIndicator = el.shadowRoot.querySelector(\n    `[name=\"${name}\"] > svg`\n  );\n  if (fallbackIndicator) {\n    return fallbackIndicator.cloneNode(true);\n  }\n  return \"\";\n}\nconst template = document.createElement(\"template\");\ntemplate.innerHTML = /*html*/\n`\n  <style>\n    :host {\n      font: var(--media-font,\n        var(--media-font-weight, normal)\n        var(--media-font-size, 14px) /\n        var(--media-text-content-height, var(--media-control-height, 24px))\n        var(--media-font-family, helvetica neue, segoe ui, roboto, arial, sans-serif));\n      color: var(--media-text-color, var(--media-primary-color, rgb(238 238 238)));\n      background: var(--media-menu-background, var(--media-control-background, var(--media-secondary-color, rgb(20 20 30 / .8))));\n      border-radius: var(--media-menu-border-radius);\n      border: var(--media-menu-border, none);\n      display: var(--media-menu-display, inline-flex);\n      transition: var(--media-menu-transition-in,\n        visibility 0s,\n        opacity .2s ease-out,\n        transform .15s ease-out,\n        left .2s ease-in-out,\n        min-width .2s ease-in-out,\n        min-height .2s ease-in-out\n      ) !important;\n      ${/* ^^Prevent transition override by media-container */\n\"\"}\n      visibility: var(--media-menu-visibility, visible);\n      opacity: var(--media-menu-opacity, 1);\n      max-height: var(--media-menu-max-height, var(--_menu-max-height, 300px));\n      transform: var(--media-menu-transform-in, translateY(0) scale(1));\n      flex-direction: column;\n      ${/* Prevent overflowing a flex container */\n\"\"}\n      min-height: 0;\n      position: relative;\n      bottom: var(--_menu-bottom);\n      box-sizing: border-box;\n    }\n\n    :host([hidden]) {\n      transition: var(--media-menu-transition-out,\n        visibility .15s ease-in,\n        opacity .15s ease-in,\n        transform .15s ease-in\n      ) !important;\n      visibility: var(--media-menu-hidden-visibility, hidden);\n      opacity: var(--media-menu-hidden-opacity, 0);\n      max-height: var(--media-menu-hidden-max-height,\n        var(--media-menu-max-height, var(--_menu-max-height, 300px)));\n      transform: var(--media-menu-transform-out, translateY(2px) scale(.99));\n      pointer-events: none;\n    }\n\n    :host([slot=\"submenu\"]) {\n      background: none;\n      width: 100%;\n      min-height: 100%;\n      position: absolute;\n      bottom: 0;\n      right: -100%;\n    }\n\n    #container {\n      display: flex;\n      flex-direction: column;\n      min-height: 0;\n      transition: transform .2s ease-out;\n      transform: translate(0, 0);\n    }\n\n    #container.has-expanded {\n      transition: transform .2s ease-in;\n      transform: translate(-100%, 0);\n    }\n\n    button {\n      background: none;\n      color: inherit;\n      border: none;\n      padding: 0;\n      font: inherit;\n      outline: inherit;\n      display: inline-flex;\n      align-items: center;\n    }\n\n    slot[name=\"header\"][hidden] {\n      display: none;\n    }\n\n    slot[name=\"header\"] > *,\n    slot[name=\"header\"]::slotted(*) {\n      padding: .4em .7em;\n      border-bottom: 1px solid rgb(255 255 255 / .25);\n      cursor: default;\n    }\n\n    slot[name=\"header\"] > button[part~=\"back\"],\n    slot[name=\"header\"]::slotted(button[part~=\"back\"]) {\n      cursor: pointer;\n    }\n\n    svg[part~=\"back\"] {\n      height: var(--media-menu-icon-height, var(--media-control-height, 24px));\n      fill: var(--media-icon-color, var(--media-primary-color, rgb(238 238 238)));\n      display: block;\n      margin-right: .5ch;\n    }\n\n    slot:not([name]) {\n      gap: var(--media-menu-gap);\n      flex-direction: var(--media-menu-flex-direction, column);\n      overflow: var(--media-menu-overflow, hidden auto);\n      display: flex;\n      min-height: 0;\n    }\n\n    :host([role=\"menu\"]) slot:not([name]) {\n      padding-block: .4em;\n    }\n\n    slot:not([name])::slotted([role=\"menu\"]) {\n      background: none;\n    }\n\n    media-chrome-menu-item > span {\n      margin-right: .5ch;\n      max-width: var(--media-menu-item-max-width);\n      text-overflow: ellipsis;\n      overflow: hidden;\n    }\n  </style>\n  <style id=\"layout-row\" media=\"width:0\">\n\n    slot[name=\"header\"] > *,\n    slot[name=\"header\"]::slotted(*) {\n      padding: .4em .5em;\n    }\n\n    slot:not([name]) {\n      gap: var(--media-menu-gap, .25em);\n      flex-direction: var(--media-menu-flex-direction, row);\n      padding-inline: .5em;\n    }\n\n    media-chrome-menu-item {\n      padding: .3em .5em;\n    }\n\n    media-chrome-menu-item[aria-checked=\"true\"] {\n      background: var(--media-menu-item-checked-background, rgb(255 255 255 / .2));\n    }\n\n    ${/* In row layout hide the checked indicator completely. */\n\"\"}\n    media-chrome-menu-item::part(checked-indicator) {\n      display: var(--media-menu-item-checked-indicator-display, none);\n    }\n  </style>\n  <div id=\"container\">\n    <slot name=\"header\" hidden>\n      <button part=\"back button\" aria-label=\"Back to previous menu\">\n        <slot name=\"back-icon\">\n          <svg aria-hidden=\"true\" viewBox=\"0 0 20 24\" part=\"back indicator\">\n            <path d=\"m11.88 17.585.742-.669-4.2-4.665 4.2-4.666-.743-.669-4.803 5.335 4.803 5.334Z\"/>\n          </svg>\n        </slot>\n        <slot name=\"title\"></slot>\n      </button>\n    </slot>\n    <slot></slot>\n  </div>\n  <slot name=\"checked-indicator\" hidden></slot>\n`;\nconst Attributes = {\n  STYLE: \"style\",\n  HIDDEN: \"hidden\",\n  DISABLED: \"disabled\",\n  ANCHOR: \"anchor\"\n};\nclass MediaChromeMenu extends globalThis.HTMLElement {\n  constructor() {\n    super();\n    __privateAdd(this, _handleSlotChange);\n    /**\n     * Sets the layout style for the menu.\n     * It can be a row or column layout. e.g. playback-rate-menu\n     */\n    __privateAdd(this, _updateLayoutStyle);\n    __privateAdd(this, _handleInvoke);\n    __privateAdd(this, _handleOpen);\n    __privateAdd(this, _handleClosed);\n    /**\n     * Updates the popover menu position based on the anchor element.\n     * @param  {number} [menuWidth]\n     */\n    __privateAdd(this, _positionMenu);\n    /**\n     * Resize this menu to fit the submenu.\n     * @param  {boolean} animate\n     */\n    __privateAdd(this, _resizeMenu);\n    __privateAdd(this, _handleClick);\n    __privateAdd(this, _backButtonElement);\n    /**\n     * Handle the toggle event of submenus.\n     * Closes all other open submenus when opening a submenu.\n     * Resizes this menu to fit the submenu.\n     *\n     * @param  {ToggleEvent} event\n     */\n    __privateAdd(this, _handleToggle);\n    /**\n     * Check if any submenu is expanded and update the container class accordingly.\n     * When the CSS :has() selector is supported, this can be done with CSS only.\n     */\n    __privateAdd(this, _checkSubmenuHasExpanded);\n    __privateAdd(this, _handleFocusOut);\n    __privateAdd(this, _handleKeyDown);\n    __privateAdd(this, _getItem);\n    __privateAdd(this, _getTabItem);\n    __privateAdd(this, _setTabItem);\n    __privateAdd(this, _selectItem);\n    __privateAdd(this, _mediaController, null);\n    __privateAdd(this, _previouslyFocused, null);\n    __privateAdd(this, _invokerElement, null);\n    __privateAdd(this, _previousItems, /* @__PURE__ */ new Set());\n    __privateAdd(this, _mutationObserver, void 0);\n    __privateAdd(this, _isPopover, false);\n    __privateAdd(this, _cssRule, null);\n    /**\n     * Fires an event when a menu item is added or removed.\n     * This is needed to update the description slot of an ancestor menu item.\n     */\n    __privateAdd(this, _handleMenuItems, () => {\n      const previousItems = __privateGet(this, _previousItems);\n      const currentItems = new Set(this.items);\n      for (const item of previousItems) {\n        if (!currentItems.has(item)) {\n          this.dispatchEvent(new CustomEvent(\"removemenuitem\", { detail: item }));\n        }\n      }\n      for (const item of currentItems) {\n        if (!previousItems.has(item)) {\n          this.dispatchEvent(new CustomEvent(\"addmenuitem\", { detail: item }));\n        }\n      }\n      __privateSet(this, _previousItems, currentItems);\n    });\n    __privateAdd(this, _handleBoundsResize, () => {\n      __privateMethod(this, _positionMenu, positionMenu_fn).call(this);\n      __privateMethod(this, _resizeMenu, resizeMenu_fn).call(this, false);\n    });\n    __privateAdd(this, _handleMenuResize, () => {\n      __privateMethod(this, _positionMenu, positionMenu_fn).call(this);\n    });\n    if (!this.shadowRoot) {\n      this.attachShadow({ mode: \"open\" });\n      this.nativeEl = this.constructor.template.content.cloneNode(true);\n      this.shadowRoot.append(this.nativeEl);\n    }\n    this.container = this.shadowRoot.querySelector(\"#container\");\n    this.defaultSlot = this.shadowRoot.querySelector(\n      \"slot:not([name])\"\n    );\n    this.shadowRoot.addEventListener(\"slotchange\", this);\n    __privateSet(this, _mutationObserver, new MutationObserver(__privateGet(this, _handleMenuItems)));\n    __privateGet(this, _mutationObserver).observe(this.defaultSlot, { childList: true });\n  }\n  static get observedAttributes() {\n    return [\n      Attributes.DISABLED,\n      Attributes.HIDDEN,\n      Attributes.STYLE,\n      Attributes.ANCHOR,\n      MediaStateReceiverAttributes.MEDIA_CONTROLLER\n    ];\n  }\n  static formatMenuItemText(text) {\n    return text;\n  }\n  enable() {\n    this.addEventListener(\"click\", this);\n    this.addEventListener(\"focusout\", this);\n    this.addEventListener(\"keydown\", this);\n    this.addEventListener(\"invoke\", this);\n    this.addEventListener(\"toggle\", this);\n  }\n  disable() {\n    this.removeEventListener(\"click\", this);\n    this.removeEventListener(\"focusout\", this);\n    this.removeEventListener(\"keyup\", this);\n    this.removeEventListener(\"invoke\", this);\n    this.removeEventListener(\"toggle\", this);\n  }\n  handleEvent(event) {\n    switch (event.type) {\n      case \"slotchange\":\n        __privateMethod(this, _handleSlotChange, handleSlotChange_fn).call(this, event);\n        break;\n      case \"invoke\":\n        __privateMethod(this, _handleInvoke, handleInvoke_fn).call(this, event);\n        break;\n      case \"click\":\n        __privateMethod(this, _handleClick, handleClick_fn).call(this, event);\n        break;\n      case \"toggle\":\n        __privateMethod(this, _handleToggle, handleToggle_fn).call(this, event);\n        break;\n      case \"focusout\":\n        __privateMethod(this, _handleFocusOut, handleFocusOut_fn).call(this, event);\n        break;\n      case \"keydown\":\n        __privateMethod(this, _handleKeyDown, handleKeyDown_fn).call(this, event);\n        break;\n    }\n  }\n  connectedCallback() {\n    var _a, _b;\n    __privateSet(this, _cssRule, insertCSSRule(this.shadowRoot, \":host\"));\n    __privateMethod(this, _updateLayoutStyle, updateLayoutStyle_fn).call(this);\n    if (!this.hasAttribute(\"disabled\")) {\n      this.enable();\n    }\n    if (!this.role) {\n      this.role = \"menu\";\n    }\n    __privateSet(this, _mediaController, getAttributeMediaController(this));\n    (_b = (_a = __privateGet(this, _mediaController)) == null ? void 0 : _a.associateElement) == null ? void 0 : _b.call(_a, this);\n    if (!this.hidden) {\n      observeResize(getBoundsElement(this), __privateGet(this, _handleBoundsResize));\n      observeResize(this, __privateGet(this, _handleMenuResize));\n    }\n  }\n  disconnectedCallback() {\n    var _a, _b;\n    unobserveResize(getBoundsElement(this), __privateGet(this, _handleBoundsResize));\n    unobserveResize(this, __privateGet(this, _handleMenuResize));\n    this.disable();\n    (_b = (_a = __privateGet(this, _mediaController)) == null ? void 0 : _a.unassociateElement) == null ? void 0 : _b.call(_a, this);\n    __privateSet(this, _mediaController, null);\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    var _a, _b, _c, _d;\n    if (attrName === Attributes.HIDDEN && newValue !== oldValue) {\n      if (!__privateGet(this, _isPopover))\n        __privateSet(this, _isPopover, true);\n      if (this.hidden) {\n        __privateMethod(this, _handleClosed, handleClosed_fn).call(this);\n      } else {\n        __privateMethod(this, _handleOpen, handleOpen_fn).call(this);\n      }\n      this.dispatchEvent(\n        new ToggleEvent({\n          oldState: this.hidden ? \"open\" : \"closed\",\n          newState: this.hidden ? \"closed\" : \"open\",\n          bubbles: true\n        })\n      );\n    } else if (attrName === MediaStateReceiverAttributes.MEDIA_CONTROLLER) {\n      if (oldValue) {\n        (_b = (_a = __privateGet(this, _mediaController)) == null ? void 0 : _a.unassociateElement) == null ? void 0 : _b.call(_a, this);\n        __privateSet(this, _mediaController, null);\n      }\n      if (newValue && this.isConnected) {\n        __privateSet(this, _mediaController, getAttributeMediaController(this));\n        (_d = (_c = __privateGet(this, _mediaController)) == null ? void 0 : _c.associateElement) == null ? void 0 : _d.call(_c, this);\n      }\n    } else if (attrName === Attributes.DISABLED && newValue !== oldValue) {\n      if (newValue == null) {\n        this.enable();\n      } else {\n        this.disable();\n      }\n    } else if (attrName === Attributes.STYLE && newValue !== oldValue) {\n      __privateMethod(this, _updateLayoutStyle, updateLayoutStyle_fn).call(this);\n    }\n  }\n  formatMenuItemText(text, data) {\n    return this.constructor.formatMenuItemText(text, data);\n  }\n  get anchor() {\n    return this.getAttribute(\"anchor\");\n  }\n  set anchor(value) {\n    this.setAttribute(\"anchor\", `${value}`);\n  }\n  /**\n   * Returns the anchor element when it is a floating menu.\n   */\n  get anchorElement() {\n    var _a;\n    if (this.anchor) {\n      return (_a = getDocumentOrShadowRoot(this)) == null ? void 0 : _a.querySelector(`#${this.anchor}`);\n    }\n    return null;\n  }\n  /**\n   * Returns the menu items.\n   */\n  get items() {\n    return this.defaultSlot.assignedElements({ flatten: true }).filter(isMenuItem);\n  }\n  get radioGroupItems() {\n    return this.items.filter((item) => item.role === \"menuitemradio\");\n  }\n  get checkedItems() {\n    return this.items.filter((item) => item.checked);\n  }\n  get value() {\n    var _a, _b;\n    return (_b = (_a = this.checkedItems[0]) == null ? void 0 : _a.value) != null ? _b : \"\";\n  }\n  set value(newValue) {\n    const item = this.items.find((item2) => item2.value === newValue);\n    if (!item)\n      return;\n    __privateMethod(this, _selectItem, selectItem_fn).call(this, item);\n  }\n  focus() {\n    __privateSet(this, _previouslyFocused, getActiveElement());\n    if (this.items.length) {\n      __privateMethod(this, _setTabItem, setTabItem_fn).call(this, this.items[0]);\n      this.items[0].focus();\n      return;\n    }\n    const focusable = this.querySelector(\n      '[autofocus], [tabindex]:not([tabindex=\"-1\"]), [role=\"menu\"]'\n    );\n    focusable == null ? void 0 : focusable.focus();\n  }\n  handleSelect(event) {\n    var _a;\n    const item = __privateMethod(this, _getItem, getItem_fn).call(this, event);\n    if (!item)\n      return;\n    __privateMethod(this, _selectItem, selectItem_fn).call(this, item, item.type === \"checkbox\");\n    if (__privateGet(this, _invokerElement) && !this.hidden) {\n      (_a = __privateGet(this, _previouslyFocused)) == null ? void 0 : _a.focus();\n      this.hidden = true;\n    }\n  }\n  get keysUsed() {\n    return [\n      \"Enter\",\n      \"Escape\",\n      \"Tab\",\n      \" \",\n      \"ArrowDown\",\n      \"ArrowUp\",\n      \"Home\",\n      \"End\"\n    ];\n  }\n  handleMove(event) {\n    var _a, _b;\n    const { key } = event;\n    const items = this.items;\n    const currentItem = (_b = (_a = __privateMethod(this, _getItem, getItem_fn).call(this, event)) != null ? _a : __privateMethod(this, _getTabItem, getTabItem_fn).call(this)) != null ? _b : items[0];\n    const currentIndex = items.indexOf(currentItem);\n    let index = Math.max(0, currentIndex);\n    if (key === \"ArrowDown\") {\n      index++;\n    } else if (key === \"ArrowUp\") {\n      index--;\n    } else if (event.key === \"Home\") {\n      index = 0;\n    } else if (event.key === \"End\") {\n      index = items.length - 1;\n    }\n    if (index < 0) {\n      index = items.length - 1;\n    }\n    if (index > items.length - 1) {\n      index = 0;\n    }\n    __privateMethod(this, _setTabItem, setTabItem_fn).call(this, items[index]);\n    items[index].focus();\n  }\n}\n_mediaController = new WeakMap();\n_previouslyFocused = new WeakMap();\n_invokerElement = new WeakMap();\n_previousItems = new WeakMap();\n_mutationObserver = new WeakMap();\n_isPopover = new WeakMap();\n_cssRule = new WeakMap();\n_handleSlotChange = new WeakSet();\nhandleSlotChange_fn = function(event) {\n  const slot = event.target;\n  for (const node of slot.assignedNodes({ flatten: true })) {\n    if (node.nodeType === 3 && node.textContent.trim() === \"\") {\n      node.remove();\n    }\n  }\n  if ([\"header\", \"title\"].includes(slot.name)) {\n    const header = this.shadowRoot.querySelector(\n      'slot[name=\"header\"]'\n    );\n    header.hidden = slot.assignedNodes().length === 0;\n  }\n  if (!slot.name) {\n    __privateGet(this, _handleMenuItems).call(this);\n  }\n};\n_handleMenuItems = new WeakMap();\n_updateLayoutStyle = new WeakSet();\nupdateLayoutStyle_fn = function() {\n  var _a;\n  const layoutRowStyle = this.shadowRoot.querySelector(\"#layout-row\");\n  const menuLayout = (_a = getComputedStyle(this).getPropertyValue(\"--media-menu-layout\")) == null ? void 0 : _a.trim();\n  layoutRowStyle.setAttribute(\"media\", menuLayout === \"row\" ? \"\" : \"width:0\");\n};\n_handleInvoke = new WeakSet();\nhandleInvoke_fn = function(event) {\n  __privateSet(this, _invokerElement, event.relatedTarget);\n  if (!containsComposedNode(this, event.relatedTarget)) {\n    this.hidden = !this.hidden;\n  }\n};\n_handleOpen = new WeakSet();\nhandleOpen_fn = function() {\n  var _a;\n  (_a = __privateGet(this, _invokerElement)) == null ? void 0 : _a.setAttribute(\"aria-expanded\", \"true\");\n  this.addEventListener(\"transitionend\", () => this.focus(), { once: true });\n  observeResize(getBoundsElement(this), __privateGet(this, _handleBoundsResize));\n  observeResize(this, __privateGet(this, _handleMenuResize));\n};\n_handleClosed = new WeakSet();\nhandleClosed_fn = function() {\n  var _a;\n  (_a = __privateGet(this, _invokerElement)) == null ? void 0 : _a.setAttribute(\"aria-expanded\", \"false\");\n  unobserveResize(getBoundsElement(this), __privateGet(this, _handleBoundsResize));\n  unobserveResize(this, __privateGet(this, _handleMenuResize));\n};\n_handleBoundsResize = new WeakMap();\n_handleMenuResize = new WeakMap();\n_positionMenu = new WeakSet();\npositionMenu_fn = function(menuWidth) {\n  if (this.hasAttribute(\"mediacontroller\") && !this.anchor)\n    return;\n  if (this.hidden || !this.anchorElement)\n    return;\n  const { x, y } = computePosition({\n    anchor: this.anchorElement,\n    floating: this,\n    placement: \"top-start\"\n  });\n  menuWidth != null ? menuWidth : menuWidth = this.offsetWidth;\n  const bounds = getBoundsElement(this);\n  const boundsRect = bounds.getBoundingClientRect();\n  const right = boundsRect.width - x - menuWidth;\n  const bottom = boundsRect.height - y - this.offsetHeight;\n  const { style } = __privateGet(this, _cssRule);\n  style.setProperty(\"position\", \"absolute\");\n  style.setProperty(\"right\", `${Math.max(0, right)}px`);\n  style.setProperty(\"--_menu-bottom\", `${bottom}px`);\n  const computedStyle = getComputedStyle(this);\n  const isBottomCalc = style.getPropertyValue(\"--_menu-bottom\") === computedStyle.bottom;\n  const realBottom = isBottomCalc ? bottom : parseFloat(computedStyle.bottom);\n  const maxHeight = boundsRect.height - realBottom - parseFloat(computedStyle.marginBottom);\n  this.style.setProperty(\"--_menu-max-height\", `${maxHeight}px`);\n};\n_resizeMenu = new WeakSet();\nresizeMenu_fn = function(animate) {\n  const expandedMenuItem = this.querySelector(\n    '[role=\"menuitem\"][aria-haspopup][aria-expanded=\"true\"]'\n  );\n  const expandedSubmenu = expandedMenuItem == null ? void 0 : expandedMenuItem.querySelector(\n    '[role=\"menu\"]'\n  );\n  const { style } = __privateGet(this, _cssRule);\n  if (!animate) {\n    style.setProperty(\"--media-menu-transition-in\", \"none\");\n  }\n  if (expandedSubmenu) {\n    const height = expandedSubmenu.offsetHeight;\n    const width = Math.max(\n      expandedSubmenu.offsetWidth,\n      expandedMenuItem.offsetWidth\n    );\n    this.style.setProperty(\"min-width\", `${width}px`);\n    this.style.setProperty(\"min-height\", `${height}px`);\n    __privateMethod(this, _positionMenu, positionMenu_fn).call(this, width);\n  } else {\n    this.style.removeProperty(\"min-width\");\n    this.style.removeProperty(\"min-height\");\n    __privateMethod(this, _positionMenu, positionMenu_fn).call(this);\n  }\n  style.removeProperty(\"--media-menu-transition-in\");\n};\n_handleClick = new WeakSet();\nhandleClick_fn = function(event) {\n  var _a;\n  event.stopPropagation();\n  if (event.composedPath().includes(__privateGet(this, _backButtonElement, backButtonElement_get))) {\n    (_a = __privateGet(this, _previouslyFocused)) == null ? void 0 : _a.focus();\n    this.hidden = true;\n    return;\n  }\n  const item = __privateMethod(this, _getItem, getItem_fn).call(this, event);\n  if (!item || item.hasAttribute(\"disabled\"))\n    return;\n  __privateMethod(this, _setTabItem, setTabItem_fn).call(this, item);\n  this.handleSelect(event);\n};\n_backButtonElement = new WeakSet();\nbackButtonElement_get = function() {\n  var _a;\n  const headerSlot = this.shadowRoot.querySelector(\n    'slot[name=\"header\"]'\n  );\n  return (_a = headerSlot.assignedElements({ flatten: true })) == null ? void 0 : _a.find(\n    (el) => el.matches('button[part~=\"back\"]')\n  );\n};\n_handleToggle = new WeakSet();\nhandleToggle_fn = function(event) {\n  if (event.target === this)\n    return;\n  __privateMethod(this, _checkSubmenuHasExpanded, checkSubmenuHasExpanded_fn).call(this);\n  const menuItemsWithSubmenu = Array.from(\n    this.querySelectorAll('[role=\"menuitem\"][aria-haspopup]')\n  );\n  for (const item of menuItemsWithSubmenu) {\n    if (item.invokeTargetElement == event.target)\n      continue;\n    if (event.newState == \"open\" && item.getAttribute(\"aria-expanded\") == \"true\" && !item.invokeTargetElement.hidden) {\n      item.invokeTargetElement.dispatchEvent(\n        new InvokeEvent({ relatedTarget: item })\n      );\n    }\n  }\n  for (const item of menuItemsWithSubmenu) {\n    item.setAttribute(\"aria-expanded\", `${!item.submenuElement.hidden}`);\n  }\n  __privateMethod(this, _resizeMenu, resizeMenu_fn).call(this, true);\n};\n_checkSubmenuHasExpanded = new WeakSet();\ncheckSubmenuHasExpanded_fn = function() {\n  const selector = '[role=\"menuitem\"] > [role=\"menu\"]:not([hidden])';\n  const expandedMenuItem = this.querySelector(selector);\n  this.container.classList.toggle(\"has-expanded\", !!expandedMenuItem);\n};\n_handleFocusOut = new WeakSet();\nhandleFocusOut_fn = function(event) {\n  var _a;\n  if (!containsComposedNode(this, event.relatedTarget)) {\n    if (__privateGet(this, _isPopover)) {\n      (_a = __privateGet(this, _previouslyFocused)) == null ? void 0 : _a.focus();\n    }\n    if (__privateGet(this, _invokerElement) && __privateGet(this, _invokerElement) !== event.relatedTarget && !this.hidden) {\n      this.hidden = true;\n    }\n  }\n};\n_handleKeyDown = new WeakSet();\nhandleKeyDown_fn = function(event) {\n  var _a, _b, _c, _d, _e;\n  const { key, ctrlKey, altKey, metaKey } = event;\n  if (ctrlKey || altKey || metaKey) {\n    return;\n  }\n  if (!this.keysUsed.includes(key)) {\n    return;\n  }\n  event.preventDefault();\n  event.stopPropagation();\n  if (key === \"Tab\") {\n    if (__privateGet(this, _isPopover)) {\n      this.hidden = true;\n      return;\n    }\n    if (event.shiftKey) {\n      (_b = (_a = this.previousElementSibling) == null ? void 0 : _a.focus) == null ? void 0 : _b.call(_a);\n    } else {\n      (_d = (_c = this.nextElementSibling) == null ? void 0 : _c.focus) == null ? void 0 : _d.call(_c);\n    }\n    this.blur();\n  } else if (key === \"Escape\") {\n    (_e = __privateGet(this, _previouslyFocused)) == null ? void 0 : _e.focus();\n    if (__privateGet(this, _isPopover)) {\n      this.hidden = true;\n    }\n  } else if (key === \"Enter\" || key === \" \") {\n    this.handleSelect(event);\n  } else {\n    this.handleMove(event);\n  }\n};\n_getItem = new WeakSet();\ngetItem_fn = function(event) {\n  return event.composedPath().find((el) => {\n    return [\"menuitemradio\", \"menuitemcheckbox\"].includes(\n      el.role\n    );\n  });\n};\n_getTabItem = new WeakSet();\ngetTabItem_fn = function() {\n  return this.items.find((item) => item.tabIndex === 0);\n};\n_setTabItem = new WeakSet();\nsetTabItem_fn = function(tabItem) {\n  for (const item of this.items) {\n    item.tabIndex = item === tabItem ? 0 : -1;\n  }\n};\n_selectItem = new WeakSet();\nselectItem_fn = function(item, toggle) {\n  const oldCheckedItems = [...this.checkedItems];\n  if (item.type === \"radio\") {\n    this.radioGroupItems.forEach((el) => el.checked = false);\n  }\n  if (toggle) {\n    item.checked = !item.checked;\n  } else {\n    item.checked = true;\n  }\n  if (this.checkedItems.some((opt, i) => opt != oldCheckedItems[i])) {\n    this.dispatchEvent(\n      new Event(\"change\", { bubbles: true, composed: true })\n    );\n  }\n};\nMediaChromeMenu.template = template;\nfunction isMenuItem(element) {\n  return [\"menuitem\", \"menuitemradio\", \"menuitemcheckbox\"].includes(\n    element == null ? void 0 : element.role\n  );\n}\nfunction getBoundsElement(host) {\n  var _a;\n  return (_a = host.getAttribute(\"bounds\") ? closestComposedNode(host, `#${host.getAttribute(\"bounds\")}`) : getMediaController(host) || host.parentElement) != null ? _a : host;\n}\nif (!globalThis.customElements.get(\"media-chrome-menu\")) {\n  globalThis.customElements.define(\"media-chrome-menu\", MediaChromeMenu);\n}\nvar media_chrome_menu_default = MediaChromeMenu;\nexport {\n  Attributes,\n  MediaChromeMenu,\n  createIndicator,\n  createMenuItem,\n  media_chrome_menu_default as default\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar __privateSet = (obj, member, value, setter) => {\n  __accessCheck(obj, member, \"write to private field\");\n  setter ? setter.call(obj, value) : member.set(obj, value);\n  return value;\n};\nvar __privateMethod = (obj, member, method) => {\n  __accessCheck(obj, member, \"access private method\");\n  return method;\n};\nvar _dirty, _ownerElement, _handleSlotChange, handleSlotChange_fn, _submenuConnected, submenuConnected_fn, _submenuDisconnected, submenuDisconnected_fn, _handleMenuItem, _handleKeyUp, handleKeyUp_fn, _handleKeyDown, handleKeyDown_fn, _reset, reset_fn;\nimport { globalThis, document } from \"../utils/server-safe-globals.js\";\nimport { InvokeEvent } from \"../utils/events.js\";\nimport {\n  getDocumentOrShadowRoot,\n  containsComposedNode\n} from \"../utils/element-utils.js\";\nconst template = document.createElement(\"template\");\ntemplate.innerHTML = /*html*/\n`\n  <style>\n    :host {\n      transition: var(--media-menu-item-transition,\n        background .15s linear,\n        opacity .2s ease-in-out\n      );\n      outline: var(--media-menu-item-outline, 0);\n      outline-offset: var(--media-menu-item-outline-offset, -1px);\n      cursor: pointer;\n      display: flex;\n      align-items: center;\n      align-self: stretch;\n      justify-self: stretch;\n      white-space: nowrap;\n      white-space-collapse: collapse;\n      text-wrap: nowrap;\n      padding: .4em .8em .4em 1em;\n    }\n\n    :host(:focus-visible) {\n      box-shadow: var(--media-menu-item-focus-shadow, inset 0 0 0 2px rgb(27 127 204 / .9));\n      outline: var(--media-menu-item-hover-outline, 0);\n      outline-offset: var(--media-menu-item-hover-outline-offset,  var(--media-menu-item-outline-offset, -1px));\n    }\n\n    :host(:hover) {\n      cursor: pointer;\n      background: var(--media-menu-item-hover-background, rgb(92 92 102 / .5));\n      outline: var(--media-menu-item-hover-outline);\n      outline-offset: var(--media-menu-item-hover-outline-offset,  var(--media-menu-item-outline-offset, -1px));\n    }\n\n    :host([aria-checked=\"true\"]) {\n      background: var(--media-menu-item-checked-background);\n    }\n\n    :host([hidden]) {\n      display: none;\n    }\n\n    :host([disabled]) {\n      pointer-events: none;\n      color: rgba(255, 255, 255, .3);\n    }\n\n    slot:not([name]) {\n      width: 100%;\n    }\n\n    slot:not([name=\"submenu\"]) {\n      display: inline-flex;\n      align-items: center;\n      transition: inherit;\n      opacity: var(--media-menu-item-opacity, 1);\n    }\n\n    slot[name=\"description\"] {\n      justify-content: end;\n    }\n\n    slot[name=\"description\"] > span {\n      display: inline-block;\n      margin-inline: 1em .2em;\n      max-width: var(--media-menu-item-description-max-width, 100px);\n      text-overflow: ellipsis;\n      overflow: hidden;\n      font-size: .8em;\n      font-weight: 400;\n      text-align: right;\n      position: relative;\n      top: .04em;\n    }\n\n    slot[name=\"checked-indicator\"] {\n      display: none;\n    }\n\n    :host(:is([role=\"menuitemradio\"],[role=\"menuitemcheckbox\"])) slot[name=\"checked-indicator\"] {\n      display: var(--media-menu-item-checked-indicator-display, inline-block);\n    }\n\n    ${/* For all slotted icons in prefix and suffix. */\n\"\"}\n    svg, img, ::slotted(svg), ::slotted(img) {\n      height: var(--media-menu-item-icon-height, var(--media-control-height, 24px));\n      fill: var(--media-icon-color, var(--media-primary-color, rgb(238 238 238)));\n      display: block;\n    }\n\n    ${/* Only for indicator icons like checked-indicator or captions-indicator. */\n\"\"}\n    [part~=\"indicator\"],\n    ::slotted([part~=\"indicator\"]) {\n      fill: var(--media-menu-item-indicator-fill,\n        var(--media-icon-color, var(--media-primary-color, rgb(238 238 238))));\n      height: var(--media-menu-item-indicator-height, 1.25em);\n      margin-right: .5ch;\n    }\n\n    [part~=\"checked-indicator\"] {\n      visibility: hidden;\n    }\n\n    :host([aria-checked=\"true\"]) [part~=\"checked-indicator\"] {\n      visibility: visible;\n    }\n  </style>\n  <slot name=\"checked-indicator\">\n    <svg aria-hidden=\"true\" viewBox=\"0 1 24 24\" part=\"checked-indicator indicator\">\n      <path d=\"m10 15.17 9.193-9.191 1.414 1.414-10.606 10.606-6.364-6.364 1.414-1.414 4.95 4.95Z\"/>\n    </svg>\n  </slot>\n  <slot name=\"prefix\"></slot>\n  <slot></slot>\n  <slot name=\"description\"></slot>\n  <slot name=\"suffix\"></slot>\n  <slot name=\"submenu\"></slot>\n`;\nconst Attributes = {\n  TYPE: \"type\",\n  VALUE: \"value\",\n  CHECKED: \"checked\",\n  DISABLED: \"disabled\"\n};\nclass MediaChromeMenuItem extends globalThis.HTMLElement {\n  constructor() {\n    super();\n    __privateAdd(this, _handleSlotChange);\n    __privateAdd(this, _submenuConnected);\n    __privateAdd(this, _submenuDisconnected);\n    __privateAdd(this, _handleKeyUp);\n    __privateAdd(this, _handleKeyDown);\n    __privateAdd(this, _reset);\n    __privateAdd(this, _dirty, false);\n    __privateAdd(this, _ownerElement, void 0);\n    /**\n     * If there is a slotted submenu the fallback content of the description slot\n     * is populated with the text of the first checked item.\n     */\n    __privateAdd(this, _handleMenuItem, () => {\n      var _a, _b;\n      this.setAttribute(\"submenusize\", `${this.submenuElement.items.length}`);\n      const descriptionSlot = this.shadowRoot.querySelector(\n        'slot[name=\"description\"]'\n      );\n      const checkedItem = (_a = this.submenuElement.checkedItems) == null ? void 0 : _a[0];\n      const description = (_b = checkedItem == null ? void 0 : checkedItem.dataset.description) != null ? _b : checkedItem == null ? void 0 : checkedItem.text;\n      const span = document.createElement(\"span\");\n      span.textContent = description != null ? description : \"\";\n      descriptionSlot.replaceChildren(span);\n    });\n    if (!this.shadowRoot) {\n      this.attachShadow({ mode: \"open\" });\n      this.shadowRoot.append(this.constructor.template.content.cloneNode(true));\n    }\n    this.shadowRoot.addEventListener(\"slotchange\", this);\n  }\n  static get observedAttributes() {\n    return [\n      Attributes.TYPE,\n      Attributes.DISABLED,\n      Attributes.CHECKED,\n      Attributes.VALUE\n    ];\n  }\n  enable() {\n    if (!this.hasAttribute(\"tabindex\")) {\n      this.setAttribute(\"tabindex\", \"-1\");\n    }\n    if (isCheckable(this) && !this.hasAttribute(\"aria-checked\")) {\n      this.setAttribute(\"aria-checked\", \"false\");\n    }\n    this.addEventListener(\"click\", this);\n    this.addEventListener(\"keydown\", this);\n  }\n  disable() {\n    this.removeAttribute(\"tabindex\");\n    this.removeEventListener(\"click\", this);\n    this.removeEventListener(\"keydown\", this);\n    this.removeEventListener(\"keyup\", this);\n  }\n  handleEvent(event) {\n    switch (event.type) {\n      case \"slotchange\":\n        __privateMethod(this, _handleSlotChange, handleSlotChange_fn).call(this, event);\n        break;\n      case \"click\":\n        this.handleClick(event);\n        break;\n      case \"keydown\":\n        __privateMethod(this, _handleKeyDown, handleKeyDown_fn).call(this, event);\n        break;\n      case \"keyup\":\n        __privateMethod(this, _handleKeyUp, handleKeyUp_fn).call(this, event);\n        break;\n    }\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    if (attrName === Attributes.CHECKED && isCheckable(this) && !__privateGet(this, _dirty)) {\n      this.setAttribute(\"aria-checked\", newValue != null ? \"true\" : \"false\");\n    } else if (attrName === Attributes.TYPE && newValue !== oldValue) {\n      this.role = \"menuitem\" + newValue;\n    } else if (attrName === Attributes.DISABLED && newValue !== oldValue) {\n      if (newValue == null) {\n        this.enable();\n      } else {\n        this.disable();\n      }\n    }\n  }\n  connectedCallback() {\n    if (!this.hasAttribute(Attributes.DISABLED)) {\n      this.enable();\n    }\n    this.role = \"menuitem\" + this.type;\n    __privateSet(this, _ownerElement, closestMenuItemsContainer(this, this.parentNode));\n    __privateMethod(this, _reset, reset_fn).call(this);\n  }\n  disconnectedCallback() {\n    this.disable();\n    __privateMethod(this, _reset, reset_fn).call(this);\n    __privateSet(this, _ownerElement, null);\n  }\n  get invokeTarget() {\n    return this.getAttribute(\"invoketarget\");\n  }\n  set invokeTarget(value) {\n    this.setAttribute(\"invoketarget\", `${value}`);\n  }\n  /**\n   * Returns the element with the id specified by the `invoketarget` attribute\n   * or the slotted submenu element.\n   */\n  get invokeTargetElement() {\n    var _a;\n    if (this.invokeTarget) {\n      return (_a = getDocumentOrShadowRoot(this)) == null ? void 0 : _a.querySelector(\n        `#${this.invokeTarget}`\n      );\n    }\n    return this.submenuElement;\n  }\n  /**\n   * Returns the slotted submenu element.\n   */\n  get submenuElement() {\n    const submenuSlot = this.shadowRoot.querySelector(\n      'slot[name=\"submenu\"]'\n    );\n    return submenuSlot.assignedElements({\n      flatten: true\n    })[0];\n  }\n  get type() {\n    var _a;\n    return (_a = this.getAttribute(Attributes.TYPE)) != null ? _a : \"\";\n  }\n  set type(val) {\n    this.setAttribute(Attributes.TYPE, `${val}`);\n  }\n  get value() {\n    var _a;\n    return (_a = this.getAttribute(Attributes.VALUE)) != null ? _a : this.text;\n  }\n  set value(val) {\n    this.setAttribute(Attributes.VALUE, val);\n  }\n  get text() {\n    var _a;\n    return ((_a = this.textContent) != null ? _a : \"\").trim();\n  }\n  get checked() {\n    if (!isCheckable(this))\n      return void 0;\n    return this.getAttribute(\"aria-checked\") === \"true\";\n  }\n  set checked(value) {\n    if (!isCheckable(this))\n      return;\n    __privateSet(this, _dirty, true);\n    this.setAttribute(\"aria-checked\", value ? \"true\" : \"false\");\n    if (value) {\n      this.part.add(\"checked\");\n    } else {\n      this.part.remove(\"checked\");\n    }\n  }\n  handleClick(event) {\n    if (isCheckable(this))\n      return;\n    if (this.invokeTargetElement && containsComposedNode(this, event.target)) {\n      this.invokeTargetElement.dispatchEvent(\n        new InvokeEvent({ relatedTarget: this })\n      );\n    }\n  }\n  get keysUsed() {\n    return [\"Enter\", \" \"];\n  }\n}\n_dirty = new WeakMap();\n_ownerElement = new WeakMap();\n_handleSlotChange = new WeakSet();\nhandleSlotChange_fn = function(event) {\n  const slot = event.target;\n  const isDefaultSlot = !(slot == null ? void 0 : slot.name);\n  if (isDefaultSlot) {\n    for (const node of slot.assignedNodes({ flatten: true })) {\n      if (node instanceof Text && node.textContent.trim() === \"\") {\n        node.remove();\n      }\n    }\n  }\n  if (slot.name === \"submenu\") {\n    if (this.submenuElement) {\n      __privateMethod(this, _submenuConnected, submenuConnected_fn).call(this);\n    } else {\n      __privateMethod(this, _submenuDisconnected, submenuDisconnected_fn).call(this);\n    }\n  }\n};\n_submenuConnected = new WeakSet();\nsubmenuConnected_fn = async function() {\n  this.setAttribute(\"aria-haspopup\", \"menu\");\n  this.setAttribute(\"aria-expanded\", `${!this.submenuElement.hidden}`);\n  this.submenuElement.addEventListener(\"change\", __privateGet(this, _handleMenuItem));\n  this.submenuElement.addEventListener(\"addmenuitem\", __privateGet(this, _handleMenuItem));\n  this.submenuElement.addEventListener(\n    \"removemenuitem\",\n    __privateGet(this, _handleMenuItem)\n  );\n  __privateGet(this, _handleMenuItem).call(this);\n};\n_submenuDisconnected = new WeakSet();\nsubmenuDisconnected_fn = function() {\n  this.removeAttribute(\"aria-haspopup\");\n  this.removeAttribute(\"aria-expanded\");\n  this.submenuElement.removeEventListener(\"change\", __privateGet(this, _handleMenuItem));\n  this.submenuElement.removeEventListener(\n    \"addmenuitem\",\n    __privateGet(this, _handleMenuItem)\n  );\n  this.submenuElement.removeEventListener(\n    \"removemenuitem\",\n    __privateGet(this, _handleMenuItem)\n  );\n  __privateGet(this, _handleMenuItem).call(this);\n};\n_handleMenuItem = new WeakMap();\n_handleKeyUp = new WeakSet();\nhandleKeyUp_fn = function(event) {\n  const { key } = event;\n  if (!this.keysUsed.includes(key)) {\n    this.removeEventListener(\"keyup\", __privateMethod(this, _handleKeyUp, handleKeyUp_fn));\n    return;\n  }\n  this.handleClick(event);\n};\n_handleKeyDown = new WeakSet();\nhandleKeyDown_fn = function(event) {\n  const { metaKey, altKey, key } = event;\n  if (metaKey || altKey || !this.keysUsed.includes(key)) {\n    this.removeEventListener(\"keyup\", __privateMethod(this, _handleKeyUp, handleKeyUp_fn));\n    return;\n  }\n  this.addEventListener(\"keyup\", __privateMethod(this, _handleKeyUp, handleKeyUp_fn), { once: true });\n};\n_reset = new WeakSet();\nreset_fn = function() {\n  var _a;\n  const items = (_a = __privateGet(this, _ownerElement)) == null ? void 0 : _a.radioGroupItems;\n  if (!items)\n    return;\n  let checkedItem = items.filter((item) => item.getAttribute(\"aria-checked\") === \"true\").pop();\n  if (!checkedItem)\n    checkedItem = items[0];\n  for (const item of items) {\n    item.setAttribute(\"aria-checked\", \"false\");\n  }\n  checkedItem == null ? void 0 : checkedItem.setAttribute(\"aria-checked\", \"true\");\n};\nMediaChromeMenuItem.template = template;\nfunction isCheckable(item) {\n  return item.type === \"radio\" || item.type === \"checkbox\";\n}\nfunction closestMenuItemsContainer(childNode, parentNode) {\n  if (!childNode)\n    return null;\n  const { host } = childNode.getRootNode();\n  if (!parentNode && host)\n    return closestMenuItemsContainer(childNode, host);\n  if (parentNode == null ? void 0 : parentNode.items)\n    return parentNode;\n  return closestMenuItemsContainer(parentNode, parentNode == null ? void 0 : parentNode.parentNode);\n}\nif (!globalThis.customElements.get(\"media-chrome-menu-item\")) {\n  globalThis.customElements.define(\n    \"media-chrome-menu-item\",\n    MediaChromeMenuItem\n  );\n}\nvar media_chrome_menu_item_default = MediaChromeMenuItem;\nexport {\n  Attributes,\n  MediaChromeMenuItem,\n  media_chrome_menu_item_default as default\n};\n", "import { globalThis, document } from \"../utils/server-safe-globals.js\";\nimport { MediaChromeMenu } from \"./media-chrome-menu.js\";\nimport { getMediaController } from \"../utils/element-utils.js\";\nconst template = document.createElement(\"template\");\ntemplate.innerHTML = MediaChromeMenu.template.innerHTML + /*html*/\n`\n  <style>\n    :host {\n      background: var(--media-settings-menu-background,\n        var(--media-menu-background,\n        var(--media-control-background,\n        var(--media-secondary-color, rgb(20 20 30 / .8)))));\n      min-width: var(--media-settings-menu-min-width, 170px);\n      border-radius: 2px 2px 0 0;\n      overflow: hidden;\n    }\n\n    :host([role=\"menu\"]) {\n      ${/* Bottom fix setting menu items for animation when the height expands. */\n\"\"}\n      justify-content: end;\n    }\n\n    slot:not([name]) {\n      justify-content: var(--media-settings-menu-justify-content);\n      flex-direction: var(--media-settings-menu-flex-direction, column);\n      overflow: visible;\n    }\n\n    #container.has-expanded {\n      --media-settings-menu-item-opacity: 0;\n    }\n  </style>\n`;\nclass MediaSettingsMenu extends MediaChromeMenu {\n  /**\n   * Returns the anchor element when it is a floating menu.\n   */\n  get anchorElement() {\n    if (this.anchor !== \"auto\")\n      return super.anchorElement;\n    return getMediaController(this).querySelector(\"media-settings-menu-button\");\n  }\n}\nMediaSettingsMenu.template = template;\nif (!globalThis.customElements.get(\"media-settings-menu\")) {\n  globalThis.customElements.define(\"media-settings-menu\", MediaSettingsMenu);\n}\nvar media_settings_menu_default = MediaSettingsMenu;\nexport {\n  MediaSettingsMenu,\n  media_settings_menu_default as default\n};\n", "var _a;\nimport { globalThis, document } from \"../utils/server-safe-globals.js\";\nimport { MediaChromeMenuItem } from \"./media-chrome-menu-item.js\";\nconst template = document.createElement(\"template\");\ntemplate.innerHTML = MediaChromeMenuItem.template.innerHTML + /*html*/\n`\n  <style>\n    slot:not([name=\"submenu\"]) {\n      opacity: var(--media-settings-menu-item-opacity, var(--media-menu-item-opacity));\n    }\n\n    :host([aria-expanded=\"true\"]:hover) {\n      background: transparent;\n    }\n  </style>\n`;\nif ((_a = template.content) == null ? void 0 : _a.querySelector) {\n  template.content.querySelector('slot[name=\"suffix\"]').innerHTML = /*html*/\n  `\n    <svg aria-hidden=\"true\" viewBox=\"0 0 20 24\">\n      <path d=\"m8.12 17.585-.742-.669 4.2-4.665-4.2-4.666.743-.669 4.803 5.335-4.803 5.334Z\"/>\n    </svg>\n  `;\n}\nclass MediaSettingsMenuItem extends MediaChromeMenuItem {\n}\nMediaSettingsMenuItem.template = template;\nif (!globalThis.customElements.get(\"media-settings-menu-item\")) {\n  globalThis.customElements.define(\n    \"media-settings-menu-item\",\n    MediaSettingsMenuItem\n  );\n}\nvar media_settings_menu_item_default = MediaSettingsMenuItem;\nexport {\n  MediaSettingsMenuItem,\n  media_settings_menu_item_default as default\n};\n", "import { MediaChromeButton } from \"../media-chrome-button.js\";\nimport { globalThis } from \"../utils/server-safe-globals.js\";\nimport { InvokeEvent } from \"../utils/events.js\";\nimport { getDocumentOrShadowRoot } from \"../utils/element-utils.js\";\nclass MediaChromeMenuButton extends MediaChromeButton {\n  connectedCallback() {\n    super.connectedCallback();\n    if (this.invokeTargetElement) {\n      this.setAttribute(\"aria-haspopup\", \"menu\");\n    }\n  }\n  get invokeTarget() {\n    return this.getAttribute(\"invoketarget\");\n  }\n  set invokeTarget(value) {\n    this.setAttribute(\"invoketarget\", `${value}`);\n  }\n  /**\n   * Returns the element with the id specified by the `invoketarget` attribute.\n   * @return {HTMLElement | null}\n   */\n  get invokeTargetElement() {\n    var _a;\n    if (this.invokeTarget) {\n      return (_a = getDocumentOrShadowRoot(this)) == null ? void 0 : _a.querySelector(\n        `#${this.invokeTarget}`\n      );\n    }\n    return null;\n  }\n  handleClick() {\n    var _a;\n    (_a = this.invokeTargetElement) == null ? void 0 : _a.dispatchEvent(\n      new InvokeEvent({ relatedTarget: this })\n    );\n  }\n}\nif (!globalThis.customElements.get(\"media-chrome-menu-button\")) {\n  globalThis.customElements.define(\n    \"media-chrome-menu-button\",\n    MediaChromeMenuButton\n  );\n}\nvar media_chrome_menu_button_default = MediaChromeMenuButton;\nexport {\n  MediaChromeMenuButton,\n  media_chrome_menu_button_default as default\n};\n", "import { MediaChromeMenuButton } from \"./media-chrome-menu-button.js\";\nimport { globalThis, document } from \"../utils/server-safe-globals.js\";\nimport { getMediaController } from \"../utils/element-utils.js\";\nimport { nouns, tooltipLabels } from \"../labels/labels.js\";\nconst slotTemplate = document.createElement(\"template\");\nslotTemplate.innerHTML = /*html*/\n`\n  <style>\n    :host([aria-expanded=\"true\"]) slot[name=tooltip] {\n      display: none;\n    }\n  </style>\n  <slot name=\"icon\">\n    <svg aria-hidden=\"true\" viewBox=\"0 0 24 24\">\n      <path d=\"M4.5 14.5a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5Zm7.5 0a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5Zm7.5 0a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5Z\"/>\n    </svg>\n  </slot>\n`;\nclass MediaSettingsMenuButton extends MediaChromeMenuButton {\n  static get observedAttributes() {\n    return [...super.observedAttributes, \"target\"];\n  }\n  constructor() {\n    super({ slotTemplate, tooltipContent: tooltipLabels.SETTINGS });\n  }\n  connectedCallback() {\n    super.connectedCallback();\n    this.setAttribute(\"aria-label\", nouns.SETTINGS());\n  }\n  /**\n   * Returns the element with the id specified by the `invoketarget` attribute.\n   * @return {HTMLElement | null}\n   */\n  get invokeTargetElement() {\n    if (this.invokeTarget != void 0)\n      return super.invokeTargetElement;\n    return getMediaController(this).querySelector(\"media-settings-menu\");\n  }\n}\nif (!globalThis.customElements.get(\"media-settings-menu-button\")) {\n  globalThis.customElements.define(\n    \"media-settings-menu-button\",\n    MediaSettingsMenuButton\n  );\n}\nvar media_settings_menu_button_default = MediaSettingsMenuButton;\nexport {\n  MediaSettingsMenuButton,\n  media_settings_menu_button_default as default\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar __privateSet = (obj, member, value, setter) => {\n  __accessCheck(obj, member, \"write to private field\");\n  setter ? setter.call(obj, value) : member.set(obj, value);\n  return value;\n};\nvar __privateMethod = (obj, member, method) => {\n  __accessCheck(obj, member, \"access private method\");\n  return method;\n};\nvar _audioTrackList, _prevState, _render, render_fn, _onChange, onChange_fn;\nimport { globalThis } from \"../utils/server-safe-globals.js\";\nimport { MediaUIAttributes, MediaUIEvents } from \"../constants.js\";\nimport { parseAudioTrackList } from \"../utils/utils.js\";\nimport {\n  MediaChromeMenu,\n  createMenuItem,\n  createIndicator\n} from \"./media-chrome-menu.js\";\nimport {\n  getStringAttr,\n  setStringAttr,\n  getMediaController\n} from \"../utils/element-utils.js\";\nclass MediaAudioTrackMenu extends MediaChromeMenu {\n  constructor() {\n    super(...arguments);\n    __privateAdd(this, _render);\n    __privateAdd(this, _onChange);\n    __privateAdd(this, _audioTrackList, []);\n    __privateAdd(this, _prevState, void 0);\n  }\n  static get observedAttributes() {\n    return [\n      ...super.observedAttributes,\n      MediaUIAttributes.MEDIA_AUDIO_TRACK_LIST,\n      MediaUIAttributes.MEDIA_AUDIO_TRACK_ENABLED,\n      MediaUIAttributes.MEDIA_AUDIO_TRACK_UNAVAILABLE\n    ];\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    super.attributeChangedCallback(attrName, oldValue, newValue);\n    if (attrName === MediaUIAttributes.MEDIA_AUDIO_TRACK_ENABLED && oldValue !== newValue) {\n      this.value = newValue;\n    } else if (attrName === MediaUIAttributes.MEDIA_AUDIO_TRACK_LIST && oldValue !== newValue) {\n      __privateSet(this, _audioTrackList, parseAudioTrackList(newValue != null ? newValue : \"\"));\n      __privateMethod(this, _render, render_fn).call(this);\n    }\n  }\n  connectedCallback() {\n    super.connectedCallback();\n    this.addEventListener(\"change\", __privateMethod(this, _onChange, onChange_fn));\n  }\n  disconnectedCallback() {\n    super.disconnectedCallback();\n    this.removeEventListener(\"change\", __privateMethod(this, _onChange, onChange_fn));\n  }\n  /**\n   * Returns the anchor element when it is a floating menu.\n   */\n  get anchorElement() {\n    var _a;\n    if (this.anchor !== \"auto\")\n      return super.anchorElement;\n    return (_a = getMediaController(this)) == null ? void 0 : _a.querySelector(\n      \"media-audio-track-menu-button\"\n    );\n  }\n  get mediaAudioTrackList() {\n    return __privateGet(this, _audioTrackList);\n  }\n  set mediaAudioTrackList(list) {\n    __privateSet(this, _audioTrackList, list);\n    __privateMethod(this, _render, render_fn).call(this);\n  }\n  /**\n   * Get enabled audio track id.\n   */\n  get mediaAudioTrackEnabled() {\n    var _a;\n    return (_a = getStringAttr(this, MediaUIAttributes.MEDIA_AUDIO_TRACK_ENABLED)) != null ? _a : \"\";\n  }\n  set mediaAudioTrackEnabled(id) {\n    setStringAttr(this, MediaUIAttributes.MEDIA_AUDIO_TRACK_ENABLED, id);\n  }\n}\n_audioTrackList = new WeakMap();\n_prevState = new WeakMap();\n_render = new WeakSet();\nrender_fn = function() {\n  if (__privateGet(this, _prevState) === JSON.stringify(this.mediaAudioTrackList))\n    return;\n  __privateSet(this, _prevState, JSON.stringify(this.mediaAudioTrackList));\n  const audioTrackList = this.mediaAudioTrackList;\n  this.defaultSlot.textContent = \"\";\n  for (const audioTrack of audioTrackList) {\n    const text = this.formatMenuItemText(audioTrack.label, audioTrack);\n    const item = createMenuItem({\n      type: \"radio\",\n      text,\n      value: `${audioTrack.id}`,\n      checked: audioTrack.enabled\n    });\n    item.prepend(createIndicator(this, \"checked-indicator\"));\n    this.defaultSlot.append(item);\n  }\n};\n_onChange = new WeakSet();\nonChange_fn = function() {\n  if (this.value == null)\n    return;\n  const event = new globalThis.CustomEvent(\n    MediaUIEvents.MEDIA_AUDIO_TRACK_REQUEST,\n    {\n      composed: true,\n      bubbles: true,\n      detail: this.value\n    }\n  );\n  this.dispatchEvent(event);\n};\nif (!globalThis.customElements.get(\"media-audio-track-menu\")) {\n  globalThis.customElements.define(\n    \"media-audio-track-menu\",\n    MediaAudioTrackMenu\n  );\n}\nvar media_audio_track_menu_default = MediaAudioTrackMenu;\nexport {\n  MediaAudioTrackMenu,\n  media_audio_track_menu_default as default\n};\n", "import { MediaUIAttributes } from \"../constants.js\";\nimport { MediaChromeMenuButton } from \"./media-chrome-menu-button.js\";\nimport { globalThis, document } from \"../utils/server-safe-globals.js\";\nimport { nouns, tooltipLabels } from \"../labels/labels.js\";\nimport {\n  getStringAttr,\n  setStringAttr,\n  getMediaController\n} from \"../utils/element-utils.js\";\nconst audioTrackIcon = (\n  /*html*/\n  `<svg aria-hidden=\"true\" viewBox=\"0 0 24 24\">\n  <path d=\"M11 17H9.5V7H11v10Zm-3-3H6.5v-4H8v4Zm6-5h-1.5v6H14V9Zm3 7h-1.5V8H17v8Z\"/>\n  <path d=\"M22 12c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2s10 4.477 10 10Zm-2 0a8 8 0 1 0-16 0 8 8 0 0 0 16 0Z\"/>\n</svg>`\n);\nconst slotTemplate = document.createElement(\"template\");\nslotTemplate.innerHTML = /*html*/\n`\n  <style>\n    :host([aria-expanded=\"true\"]) slot[name=tooltip] {\n      display: none;\n    }\n  </style>\n  <slot name=\"icon\">${audioTrackIcon}</slot>\n`;\nclass MediaAudioTrackMenuButton extends MediaChromeMenuButton {\n  static get observedAttributes() {\n    return [\n      ...super.observedAttributes,\n      MediaUIAttributes.MEDIA_AUDIO_TRACK_ENABLED,\n      MediaUIAttributes.MEDIA_AUDIO_TRACK_UNAVAILABLE\n    ];\n  }\n  constructor() {\n    super({ slotTemplate, tooltipContent: tooltipLabels.AUDIO_TRACK_MENU });\n  }\n  connectedCallback() {\n    super.connectedCallback();\n    this.setAttribute(\"aria-label\", nouns.AUDIO_TRACKS());\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    super.attributeChangedCallback(attrName, oldValue, newValue);\n  }\n  /**\n   * Returns the element with the id specified by the `invoketarget` attribute.\n   * @return {HTMLElement | null}\n   */\n  get invokeTargetElement() {\n    var _a;\n    if (this.invokeTarget != void 0)\n      return super.invokeTargetElement;\n    return (_a = getMediaController(this)) == null ? void 0 : _a.querySelector(\"media-audio-track-menu\");\n  }\n  /**\n   * Get enabled audio track id.\n   * @return {string}\n   */\n  get mediaAudioTrackEnabled() {\n    var _a;\n    return (_a = getStringAttr(this, MediaUIAttributes.MEDIA_AUDIO_TRACK_ENABLED)) != null ? _a : \"\";\n  }\n  set mediaAudioTrackEnabled(id) {\n    setStringAttr(this, MediaUIAttributes.MEDIA_AUDIO_TRACK_ENABLED, id);\n  }\n}\nif (!globalThis.customElements.get(\"media-audio-track-menu-button\")) {\n  globalThis.customElements.define(\n    \"media-audio-track-menu-button\",\n    MediaAudioTrackMenuButton\n  );\n}\nvar media_audio_track_menu_button_default = MediaAudioTrackMenuButton;\nexport {\n  MediaAudioTrackMenuButton,\n  media_audio_track_menu_button_default as default\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar __privateSet = (obj, member, value, setter) => {\n  __accessCheck(obj, member, \"write to private field\");\n  setter ? setter.call(obj, value) : member.set(obj, value);\n  return value;\n};\nvar __privateMethod = (obj, member, method) => {\n  __accessCheck(obj, member, \"access private method\");\n  return method;\n};\nvar _prevState, _render, render_fn, _onChange, onChange_fn;\nimport { globalThis, document } from \"../utils/server-safe-globals.js\";\nimport { MediaUIAttributes, MediaUIEvents } from \"../constants.js\";\nimport { getMediaController } from \"../utils/element-utils.js\";\nimport {\n  MediaChromeMenu,\n  createMenuItem,\n  createIndicator\n} from \"./media-chrome-menu.js\";\nimport {\n  parseTextTracksStr,\n  stringifyTextTrackList,\n  formatTextTrackObj\n} from \"../utils/captions.js\";\nconst ccIcon = (\n  /*html*/\n  `\n  <svg aria-hidden=\"true\" viewBox=\"0 0 26 24\" part=\"captions-indicator indicator\">\n    <path d=\"M22.83 5.68a2.58 2.58 0 0 0-2.3-2.5c-3.62-.24-11.44-.24-15.06 0a2.58 2.58 0 0 0-2.3 2.5c-.23 4.21-.23 8.43 0 12.64a2.58 2.58 0 0 0 2.3 2.5c3.62.24 11.44.24 15.06 0a2.58 2.58 0 0 0 2.3-2.5c.23-4.21.23-8.43 0-12.64Zm-11.39 9.45a3.07 3.07 0 0 1-1.91.57 3.06 3.06 0 0 1-2.34-1 3.75 3.75 0 0 1-.92-2.67 3.92 3.92 0 0 1 .92-2.77 3.18 3.18 0 0 1 2.43-1 2.94 2.94 0 0 1 2.13.78c.364.359.62.813.74 1.31l-1.43.35a1.49 1.49 0 0 0-1.51-1.17 1.61 1.61 0 0 0-1.29.58 2.79 2.79 0 0 0-.5 1.89 3 3 0 0 0 .49 1.93 1.61 1.61 0 0 0 1.27.58 1.48 1.48 0 0 0 1-.37 2.1 2.1 0 0 0 .59-1.14l1.4.44a3.23 3.23 0 0 1-1.07 1.69Zm7.22 0a3.07 3.07 0 0 1-1.91.57 3.06 3.06 0 0 1-2.34-1 3.75 3.75 0 0 1-.92-2.67 3.88 3.88 0 0 1 .93-2.77 3.14 3.14 0 0 1 2.42-1 3 3 0 0 1 2.16.82 2.8 2.8 0 0 1 .73 1.31l-1.43.35a1.49 1.49 0 0 0-1.51-1.21 1.61 1.61 0 0 0-1.29.58A2.79 2.79 0 0 0 15 12a3 3 0 0 0 .49 1.93 1.61 1.61 0 0 0 1.27.58 1.44 1.44 0 0 0 1-.37 2.1 2.1 0 0 0 .6-1.15l1.4.44a3.17 3.17 0 0 1-1.1 1.7Z\"/>\n  </svg>`\n);\nconst template = document.createElement(\"template\");\ntemplate.innerHTML = MediaChromeMenu.template.innerHTML + /*html*/\n`\n  <slot name=\"captions-indicator\" hidden>${ccIcon}</slot>`;\nclass MediaCaptionsMenu extends MediaChromeMenu {\n  constructor() {\n    super(...arguments);\n    __privateAdd(this, _render);\n    __privateAdd(this, _onChange);\n    __privateAdd(this, _prevState, void 0);\n  }\n  static get observedAttributes() {\n    return [\n      ...super.observedAttributes,\n      MediaUIAttributes.MEDIA_SUBTITLES_LIST,\n      MediaUIAttributes.MEDIA_SUBTITLES_SHOWING\n    ];\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    super.attributeChangedCallback(attrName, oldValue, newValue);\n    if (attrName === MediaUIAttributes.MEDIA_SUBTITLES_LIST && oldValue !== newValue) {\n      __privateMethod(this, _render, render_fn).call(this);\n    } else if (attrName === MediaUIAttributes.MEDIA_SUBTITLES_SHOWING && oldValue !== newValue) {\n      this.value = newValue;\n    }\n  }\n  connectedCallback() {\n    super.connectedCallback();\n    this.addEventListener(\"change\", __privateMethod(this, _onChange, onChange_fn));\n  }\n  disconnectedCallback() {\n    super.disconnectedCallback();\n    this.removeEventListener(\"change\", __privateMethod(this, _onChange, onChange_fn));\n  }\n  /**\n   * Returns the anchor element when it is a floating menu.\n   */\n  get anchorElement() {\n    if (this.anchor !== \"auto\")\n      return super.anchorElement;\n    return getMediaController(this).querySelector(\"media-captions-menu-button\");\n  }\n  /**\n   * @type {Array<object>} An array of TextTrack-like objects.\n   * Objects must have the properties: kind, language, and label.\n   */\n  get mediaSubtitlesList() {\n    return getSubtitlesListAttr(this, MediaUIAttributes.MEDIA_SUBTITLES_LIST);\n  }\n  set mediaSubtitlesList(list) {\n    setSubtitlesListAttr(this, MediaUIAttributes.MEDIA_SUBTITLES_LIST, list);\n  }\n  /**\n   * An array of TextTrack-like objects.\n   * Objects must have the properties: kind, language, and label.\n   */\n  get mediaSubtitlesShowing() {\n    return getSubtitlesListAttr(\n      this,\n      MediaUIAttributes.MEDIA_SUBTITLES_SHOWING\n    );\n  }\n  set mediaSubtitlesShowing(list) {\n    setSubtitlesListAttr(this, MediaUIAttributes.MEDIA_SUBTITLES_SHOWING, list);\n  }\n}\n_prevState = new WeakMap();\n_render = new WeakSet();\nrender_fn = function() {\n  var _a;\n  if (__privateGet(this, _prevState) === JSON.stringify(this.mediaSubtitlesList))\n    return;\n  __privateSet(this, _prevState, JSON.stringify(this.mediaSubtitlesList));\n  this.defaultSlot.textContent = \"\";\n  const isOff = !this.value;\n  const item = createMenuItem({\n    type: \"radio\",\n    text: this.formatMenuItemText(\"Off\"),\n    value: \"off\",\n    checked: isOff\n  });\n  item.prepend(createIndicator(this, \"checked-indicator\"));\n  this.defaultSlot.append(item);\n  const subtitlesList = this.mediaSubtitlesList;\n  for (const subs of subtitlesList) {\n    const item2 = createMenuItem({\n      type: \"radio\",\n      text: this.formatMenuItemText(subs.label, subs),\n      value: formatTextTrackObj(subs),\n      checked: this.value == formatTextTrackObj(subs)\n    });\n    item2.prepend(createIndicator(this, \"checked-indicator\"));\n    const type = (_a = subs.kind) != null ? _a : \"subs\";\n    if (type === \"captions\") {\n      item2.append(createIndicator(this, \"captions-indicator\"));\n    }\n    this.defaultSlot.append(item2);\n  }\n};\n_onChange = new WeakSet();\nonChange_fn = function() {\n  const showingSubs = this.mediaSubtitlesShowing;\n  const showingSubsStr = this.getAttribute(\n    MediaUIAttributes.MEDIA_SUBTITLES_SHOWING\n  );\n  const localStateChange = this.value !== showingSubsStr;\n  if ((showingSubs == null ? void 0 : showingSubs.length) && localStateChange) {\n    this.dispatchEvent(\n      new globalThis.CustomEvent(\n        MediaUIEvents.MEDIA_DISABLE_SUBTITLES_REQUEST,\n        {\n          composed: true,\n          bubbles: true,\n          detail: showingSubs\n        }\n      )\n    );\n  }\n  if (!this.value || !localStateChange)\n    return;\n  const event = new globalThis.CustomEvent(\n    MediaUIEvents.MEDIA_SHOW_SUBTITLES_REQUEST,\n    {\n      composed: true,\n      bubbles: true,\n      detail: this.value\n    }\n  );\n  this.dispatchEvent(event);\n};\nMediaCaptionsMenu.template = template;\nconst getSubtitlesListAttr = (el, attrName) => {\n  const attrVal = el.getAttribute(attrName);\n  return attrVal ? parseTextTracksStr(attrVal) : [];\n};\nconst setSubtitlesListAttr = (el, attrName, list) => {\n  if (!(list == null ? void 0 : list.length)) {\n    el.removeAttribute(attrName);\n    return;\n  }\n  const newValStr = stringifyTextTrackList(list);\n  const oldVal = el.getAttribute(attrName);\n  if (oldVal === newValStr)\n    return;\n  el.setAttribute(attrName, newValStr);\n};\nif (!globalThis.customElements.get(\"media-captions-menu\")) {\n  globalThis.customElements.define(\"media-captions-menu\", MediaCaptionsMenu);\n}\nvar media_captions_menu_default = MediaCaptionsMenu;\nexport {\n  MediaCaptionsMenu,\n  media_captions_menu_default as default\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar __privateSet = (obj, member, value, setter) => {\n  __accessCheck(obj, member, \"write to private field\");\n  setter ? setter.call(obj, value) : member.set(obj, value);\n  return value;\n};\nvar _captionsReady;\nimport { globalThis, document } from \"../utils/server-safe-globals.js\";\nimport { MediaUIAttributes } from \"../constants.js\";\nimport { nouns, tooltipLabels } from \"../labels/labels.js\";\nimport { MediaChromeMenuButton } from \"./media-chrome-menu-button.js\";\nimport { getMediaController } from \"../utils/element-utils.js\";\nimport {\n  areSubsOn,\n  parseTextTracksStr,\n  stringifyTextTrackList\n} from \"../utils/captions.js\";\nconst ccIconOn = `<svg aria-hidden=\"true\" viewBox=\"0 0 26 24\">\n  <path d=\"M22.83 5.68a2.58 2.58 0 0 0-2.3-2.5c-3.62-.24-11.44-.24-15.06 0a2.58 2.58 0 0 0-2.3 2.5c-.23 4.21-.23 8.43 0 12.64a2.58 2.58 0 0 0 2.3 2.5c3.62.24 11.44.24 15.06 0a2.58 2.58 0 0 0 2.3-2.5c.23-4.21.23-8.43 0-12.64Zm-11.39 9.45a3.07 3.07 0 0 1-1.91.57 3.06 3.06 0 0 1-2.34-1 3.75 3.75 0 0 1-.92-2.67 3.92 3.92 0 0 1 .92-2.77 3.18 3.18 0 0 1 2.43-1 2.94 2.94 0 0 1 2.13.78c.364.359.62.813.74 1.31l-1.43.35a1.49 1.49 0 0 0-1.51-1.17 1.61 1.61 0 0 0-1.29.58 2.79 2.79 0 0 0-.5 1.89 3 3 0 0 0 .49 1.93 1.61 1.61 0 0 0 1.27.58 1.48 1.48 0 0 0 1-.37 2.1 2.1 0 0 0 .59-1.14l1.4.44a3.23 3.23 0 0 1-1.07 1.69Zm7.22 0a3.07 3.07 0 0 1-1.91.57 3.06 3.06 0 0 1-2.34-1 3.75 3.75 0 0 1-.92-2.67 3.88 3.88 0 0 1 .93-2.77 3.14 3.14 0 0 1 2.42-1 3 3 0 0 1 2.16.82 2.8 2.8 0 0 1 .73 1.31l-1.43.35a1.49 1.49 0 0 0-1.51-1.21 1.61 1.61 0 0 0-1.29.58A2.79 2.79 0 0 0 15 12a3 3 0 0 0 .49 1.93 1.61 1.61 0 0 0 1.27.58 1.44 1.44 0 0 0 1-.37 2.1 2.1 0 0 0 .6-1.15l1.4.44a3.17 3.17 0 0 1-1.1 1.7Z\"/>\n</svg>`;\nconst ccIconOff = `<svg aria-hidden=\"true\" viewBox=\"0 0 26 24\">\n  <path d=\"M17.73 14.09a1.4 1.4 0 0 1-1 .37 1.579 1.579 0 0 1-1.27-.58A3 3 0 0 1 15 12a2.8 2.8 0 0 1 .5-1.85 1.63 1.63 0 0 1 1.29-.57 1.47 1.47 0 0 1 1.51 1.2l1.43-.34A2.89 2.89 0 0 0 19 9.07a3 3 0 0 0-2.14-.78 3.14 3.14 0 0 0-2.42 1 3.91 3.91 0 0 0-.93 2.78 3.74 3.74 0 0 0 .92 2.66 3.07 3.07 0 0 0 2.34 1 3.07 3.07 0 0 0 1.91-.57 3.17 3.17 0 0 0 1.07-1.74l-1.4-.45c-.083.43-.3.822-.62 1.12Zm-7.22 0a1.43 1.43 0 0 1-1 .37 1.58 1.58 0 0 1-1.27-.58A3 3 0 0 1 7.76 12a2.8 2.8 0 0 1 .5-1.85 1.63 1.63 0 0 1 1.29-.57 1.47 1.47 0 0 1 1.51 1.2l1.43-.34a2.81 2.81 0 0 0-.74-1.32 2.94 2.94 0 0 0-2.13-.78 3.18 3.18 0 0 0-2.43 1 4 4 0 0 0-.92 2.78 3.74 3.74 0 0 0 .92 2.66 3.07 3.07 0 0 0 2.34 1 3.07 3.07 0 0 0 1.91-.57 3.23 3.23 0 0 0 1.07-1.74l-1.4-.45a2.06 2.06 0 0 1-.6 1.07Zm12.32-8.41a2.59 2.59 0 0 0-2.3-2.51C18.72 3.05 15.86 3 13 3c-2.86 0-5.72.05-7.53.17a2.59 2.59 0 0 0-2.3 2.51c-.23 4.207-.23 8.423 0 12.63a2.57 2.57 0 0 0 2.3 2.5c1.81.13 4.67.19 7.53.19 2.86 0 5.72-.06 7.53-.19a2.57 2.57 0 0 0 2.3-2.5c.23-4.207.23-8.423 0-12.63Zm-1.49 12.53a1.11 1.11 0 0 1-.91 1.11c-1.67.11-4.45.18-7.43.18-2.98 0-5.76-.07-7.43-.18a1.11 1.11 0 0 1-.91-1.11c-.21-4.14-.21-8.29 0-12.43a1.11 1.11 0 0 1 .91-1.11C7.24 4.56 10 4.49 13 4.49s5.76.07 7.43.18a1.11 1.11 0 0 1 .91 1.11c.21 4.14.21 8.29 0 12.43Z\"/>\n</svg>`;\nconst slotTemplate = document.createElement(\"template\");\nslotTemplate.innerHTML = /*html*/\n`\n  <style>\n    :host([aria-checked=\"true\"]) slot[name=off] {\n      display: none !important;\n    }\n\n    ${/* Double negative, but safer if display doesn't equal 'block' */\n\"\"}\n    :host(:not([aria-checked=\"true\"])) slot[name=on] {\n      display: none !important;\n    }\n\n    :host([aria-expanded=\"true\"]) slot[name=tooltip] {\n      display: none;\n    }\n  </style>\n\n  <slot name=\"icon\">\n    <slot name=\"on\">${ccIconOn}</slot>\n    <slot name=\"off\">${ccIconOff}</slot>\n  </slot>\n`;\nconst updateAriaChecked = (el) => {\n  el.setAttribute(\"aria-checked\", areSubsOn(el).toString());\n};\nclass MediaCaptionsMenuButton extends MediaChromeMenuButton {\n  constructor(options = {}) {\n    super({ slotTemplate, tooltipContent: tooltipLabels.CAPTIONS, ...options });\n    __privateAdd(this, _captionsReady, void 0);\n    __privateSet(this, _captionsReady, false);\n  }\n  static get observedAttributes() {\n    return [\n      ...super.observedAttributes,\n      MediaUIAttributes.MEDIA_SUBTITLES_LIST,\n      MediaUIAttributes.MEDIA_SUBTITLES_SHOWING\n    ];\n  }\n  connectedCallback() {\n    super.connectedCallback();\n    this.setAttribute(\"aria-label\", nouns.CLOSED_CAPTIONS());\n    updateAriaChecked(this);\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    super.attributeChangedCallback(attrName, oldValue, newValue);\n    if (attrName === MediaUIAttributes.MEDIA_SUBTITLES_SHOWING) {\n      updateAriaChecked(this);\n    }\n  }\n  /**\n   * Returns the element with the id specified by the `invoketarget` attribute.\n   * @return {HTMLElement | null}\n   */\n  get invokeTargetElement() {\n    var _a;\n    if (this.invokeTarget != void 0)\n      return super.invokeTargetElement;\n    return (_a = getMediaController(this)) == null ? void 0 : _a.querySelector(\"media-captions-menu\");\n  }\n  /**\n   * An array of TextTrack-like objects.\n   * Objects must have the properties: kind, language, and label.\n   */\n  get mediaSubtitlesList() {\n    return getSubtitlesListAttr(this, MediaUIAttributes.MEDIA_SUBTITLES_LIST);\n  }\n  set mediaSubtitlesList(list) {\n    setSubtitlesListAttr(this, MediaUIAttributes.MEDIA_SUBTITLES_LIST, list);\n  }\n  /**\n   * An array of TextTrack-like objects.\n   * Objects must have the properties: kind, language, and label.\n   */\n  get mediaSubtitlesShowing() {\n    return getSubtitlesListAttr(\n      this,\n      MediaUIAttributes.MEDIA_SUBTITLES_SHOWING\n    );\n  }\n  set mediaSubtitlesShowing(list) {\n    setSubtitlesListAttr(this, MediaUIAttributes.MEDIA_SUBTITLES_SHOWING, list);\n  }\n}\n_captionsReady = new WeakMap();\nconst getSubtitlesListAttr = (el, attrName) => {\n  const attrVal = el.getAttribute(attrName);\n  return attrVal ? parseTextTracksStr(attrVal) : [];\n};\nconst setSubtitlesListAttr = (el, attrName, list) => {\n  if (!(list == null ? void 0 : list.length)) {\n    el.removeAttribute(attrName);\n    return;\n  }\n  const newValStr = stringifyTextTrackList(list);\n  const oldVal = el.getAttribute(attrName);\n  if (oldVal === newValStr)\n    return;\n  el.setAttribute(attrName, newValStr);\n};\nif (!globalThis.customElements.get(\"media-captions-menu-button\")) {\n  globalThis.customElements.define(\n    \"media-captions-menu-button\",\n    MediaCaptionsMenuButton\n  );\n}\nvar media_captions_menu_button_default = MediaCaptionsMenuButton;\nexport {\n  MediaCaptionsMenuButton,\n  media_captions_menu_button_default as default\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar __privateMethod = (obj, member, method) => {\n  __accessCheck(obj, member, \"access private method\");\n  return method;\n};\nvar _rates, _render, render_fn, _onChange, onChange_fn;\nimport { globalThis } from \"../utils/server-safe-globals.js\";\nimport { MediaUIAttributes, MediaUIEvents } from \"../constants.js\";\nimport { AttributeTokenList } from \"../utils/attribute-token-list.js\";\nimport {\n  getNumericAttr,\n  setNumericAttr,\n  getMediaController\n} from \"../utils/element-utils.js\";\nimport { DEFAULT_RATES, DEFAULT_RATE } from \"../media-playback-rate-button.js\";\nimport {\n  MediaChromeMenu,\n  createMenuItem,\n  createIndicator\n} from \"./media-chrome-menu.js\";\nconst Attributes = {\n  RATES: \"rates\"\n};\nclass MediaPlaybackRateMenu extends MediaChromeMenu {\n  constructor() {\n    super();\n    __privateAdd(this, _render);\n    __privateAdd(this, _onChange);\n    __privateAdd(this, _rates, new AttributeTokenList(this, Attributes.RATES, {\n      defaultValue: DEFAULT_RATES\n    }));\n    __privateMethod(this, _render, render_fn).call(this);\n  }\n  static get observedAttributes() {\n    return [\n      ...super.observedAttributes,\n      MediaUIAttributes.MEDIA_PLAYBACK_RATE,\n      Attributes.RATES\n    ];\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    super.attributeChangedCallback(attrName, oldValue, newValue);\n    if (attrName === MediaUIAttributes.MEDIA_PLAYBACK_RATE && oldValue != newValue) {\n      this.value = newValue;\n    } else if (attrName === Attributes.RATES && oldValue != newValue) {\n      __privateGet(this, _rates).value = newValue;\n      __privateMethod(this, _render, render_fn).call(this);\n    }\n  }\n  connectedCallback() {\n    super.connectedCallback();\n    this.addEventListener(\"change\", __privateMethod(this, _onChange, onChange_fn));\n  }\n  disconnectedCallback() {\n    super.disconnectedCallback();\n    this.removeEventListener(\"change\", __privateMethod(this, _onChange, onChange_fn));\n  }\n  /**\n   * Returns the anchor element when it is a floating menu.\n   */\n  get anchorElement() {\n    if (this.anchor !== \"auto\")\n      return super.anchorElement;\n    return getMediaController(this).querySelector(\n      \"media-playback-rate-menu-button\"\n    );\n  }\n  /**\n   * Will return a DOMTokenList.\n   * Setting a value will accept an array of numbers.\n   */\n  get rates() {\n    return __privateGet(this, _rates);\n  }\n  set rates(value) {\n    if (!value) {\n      __privateGet(this, _rates).value = \"\";\n    } else if (Array.isArray(value)) {\n      __privateGet(this, _rates).value = value.join(\" \");\n    }\n    __privateMethod(this, _render, render_fn).call(this);\n  }\n  /**\n   * The current playback rate\n   */\n  get mediaPlaybackRate() {\n    return getNumericAttr(\n      this,\n      MediaUIAttributes.MEDIA_PLAYBACK_RATE,\n      DEFAULT_RATE\n    );\n  }\n  set mediaPlaybackRate(value) {\n    setNumericAttr(this, MediaUIAttributes.MEDIA_PLAYBACK_RATE, value);\n  }\n}\n_rates = new WeakMap();\n_render = new WeakSet();\nrender_fn = function() {\n  this.defaultSlot.textContent = \"\";\n  for (const rate of this.rates) {\n    const item = createMenuItem({\n      type: \"radio\",\n      text: this.formatMenuItemText(`${rate}x`, rate),\n      value: rate,\n      checked: this.mediaPlaybackRate == rate\n    });\n    item.prepend(createIndicator(this, \"checked-indicator\"));\n    this.defaultSlot.append(item);\n  }\n};\n_onChange = new WeakSet();\nonChange_fn = function() {\n  if (!this.value)\n    return;\n  const event = new globalThis.CustomEvent(\n    MediaUIEvents.MEDIA_PLAYBACK_RATE_REQUEST,\n    {\n      composed: true,\n      bubbles: true,\n      detail: this.value\n    }\n  );\n  this.dispatchEvent(event);\n};\nif (!globalThis.customElements.get(\"media-playback-rate-menu\")) {\n  globalThis.customElements.define(\n    \"media-playback-rate-menu\",\n    MediaPlaybackRateMenu\n  );\n}\nvar media_playback_rate_menu_default = MediaPlaybackRateMenu;\nexport {\n  Attributes,\n  MediaPlaybackRateMenu,\n  media_playback_rate_menu_default as default\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar _rates;\nimport { globalThis, document } from \"../utils/server-safe-globals.js\";\nimport { MediaUIAttributes } from \"../constants.js\";\nimport { nouns, tooltipLabels } from \"../labels/labels.js\";\nimport { MediaChromeMenuButton } from \"./media-chrome-menu-button.js\";\nimport { AttributeTokenList } from \"../utils/attribute-token-list.js\";\nimport {\n  getNumericAttr,\n  setNumericAttr,\n  getMediaController\n} from \"../utils/element-utils.js\";\nconst Attributes = {\n  RATES: \"rates\"\n};\nconst DEFAULT_RATES = [1, 1.2, 1.5, 1.7, 2];\nconst DEFAULT_RATE = 1;\nconst slotTemplate = document.createElement(\"template\");\nslotTemplate.innerHTML = /*html*/\n`\n  <style>\n    :host {\n      min-width: 5ch;\n      padding: var(--media-button-padding, var(--media-control-padding, 10px 5px));\n    }\n    \n    :host([aria-expanded=\"true\"]) slot[name=tooltip] {\n      display: none;\n    }\n  </style>\n  <slot name=\"icon\"></slot>\n`;\nclass MediaPlaybackRateMenuButton extends MediaChromeMenuButton {\n  constructor(options = {}) {\n    super({\n      slotTemplate,\n      tooltipContent: tooltipLabels.PLAYBACK_RATE,\n      ...options\n    });\n    __privateAdd(this, _rates, new AttributeTokenList(this, Attributes.RATES, {\n      defaultValue: DEFAULT_RATES\n    }));\n    this.container = this.shadowRoot.querySelector('slot[name=\"icon\"]');\n    this.container.innerHTML = `${DEFAULT_RATE}x`;\n  }\n  static get observedAttributes() {\n    return [\n      ...super.observedAttributes,\n      MediaUIAttributes.MEDIA_PLAYBACK_RATE,\n      Attributes.RATES\n    ];\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    super.attributeChangedCallback(attrName, oldValue, newValue);\n    if (attrName === Attributes.RATES) {\n      __privateGet(this, _rates).value = newValue;\n    }\n    if (attrName === MediaUIAttributes.MEDIA_PLAYBACK_RATE) {\n      const newPlaybackRate = newValue ? +newValue : Number.NaN;\n      const playbackRate = !Number.isNaN(newPlaybackRate) ? newPlaybackRate : DEFAULT_RATE;\n      this.container.innerHTML = `${playbackRate}x`;\n      this.setAttribute(\"aria-label\", nouns.PLAYBACK_RATE({ playbackRate }));\n    }\n  }\n  /**\n   * Returns the element with the id specified by the `invoketarget` attribute.\n   */\n  get invokeTargetElement() {\n    if (this.invokeTarget != void 0)\n      return super.invokeTargetElement;\n    return getMediaController(this).querySelector(\"media-playback-rate-menu\");\n  }\n  /**\n   * Will return a DOMTokenList.\n   * Setting a value will accept an array of numbers.\n   */\n  get rates() {\n    return __privateGet(this, _rates);\n  }\n  set rates(value) {\n    if (!value) {\n      __privateGet(this, _rates).value = \"\";\n    } else if (Array.isArray(value)) {\n      __privateGet(this, _rates).value = value.join(\" \");\n    }\n  }\n  /**\n   * The current playback rate\n   */\n  get mediaPlaybackRate() {\n    return getNumericAttr(\n      this,\n      MediaUIAttributes.MEDIA_PLAYBACK_RATE,\n      DEFAULT_RATE\n    );\n  }\n  set mediaPlaybackRate(value) {\n    setNumericAttr(this, MediaUIAttributes.MEDIA_PLAYBACK_RATE, value);\n  }\n}\n_rates = new WeakMap();\nif (!globalThis.customElements.get(\"media-playback-rate-menu-button\")) {\n  globalThis.customElements.define(\n    \"media-playback-rate-menu-button\",\n    MediaPlaybackRateMenuButton\n  );\n}\nvar media_playback_rate_menu_button_default = MediaPlaybackRateMenuButton;\nexport {\n  Attributes,\n  DEFAULT_RATE,\n  DEFAULT_RATES,\n  MediaPlaybackRateMenuButton,\n  media_playback_rate_menu_button_default as default\n};\n", "var __accessCheck = (obj, member, msg) => {\n  if (!member.has(obj))\n    throw TypeError(\"Cannot \" + msg);\n};\nvar __privateGet = (obj, member, getter) => {\n  __accessCheck(obj, member, \"read from private field\");\n  return getter ? getter.call(obj) : member.get(obj);\n};\nvar __privateAdd = (obj, member, value) => {\n  if (member.has(obj))\n    throw TypeError(\"Cannot add the same private member more than once\");\n  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n};\nvar __privateSet = (obj, member, value, setter) => {\n  __accessCheck(obj, member, \"write to private field\");\n  setter ? setter.call(obj, value) : member.set(obj, value);\n  return value;\n};\nvar __privateMethod = (obj, member, method) => {\n  __accessCheck(obj, member, \"access private method\");\n  return method;\n};\nvar _renditionList, _prevState, _render, render_fn, _onChange, onChange_fn;\nimport { globalThis } from \"../utils/server-safe-globals.js\";\nimport { MediaUIAttributes, MediaUIEvents } from \"../constants.js\";\nimport {\n  getMediaController,\n  getStringAttr,\n  setStringAttr,\n  getNumericAttr,\n  setNumericAttr\n} from \"../utils/element-utils.js\";\nimport { parseRenditionList } from \"../utils/utils.js\";\nimport {\n  MediaChromeMenu,\n  createMenuItem,\n  createIndicator\n} from \"./media-chrome-menu.js\";\nclass MediaRenditionMenu extends MediaChromeMenu {\n  constructor() {\n    super(...arguments);\n    __privateAdd(this, _render);\n    __privateAdd(this, _onChange);\n    __privateAdd(this, _renditionList, []);\n    __privateAdd(this, _prevState, {});\n  }\n  static get observedAttributes() {\n    return [\n      ...super.observedAttributes,\n      MediaUIAttributes.MEDIA_RENDITION_LIST,\n      MediaUIAttributes.MEDIA_RENDITION_SELECTED,\n      MediaUIAttributes.MEDIA_RENDITION_UNAVAILABLE,\n      MediaUIAttributes.MEDIA_HEIGHT\n    ];\n  }\n  attributeChangedCallback(attrName, oldValue, newValue) {\n    super.attributeChangedCallback(attrName, oldValue, newValue);\n    if (attrName === MediaUIAttributes.MEDIA_RENDITION_SELECTED && oldValue !== newValue) {\n      this.value = newValue != null ? newValue : \"auto\";\n    } else if (attrName === MediaUIAttributes.MEDIA_RENDITION_LIST && oldValue !== newValue) {\n      __privateSet(this, _renditionList, parseRenditionList(newValue));\n      __privateMethod(this, _render, render_fn).call(this);\n    } else if (attrName === MediaUIAttributes.MEDIA_HEIGHT && oldValue !== newValue) {\n      __privateMethod(this, _render, render_fn).call(this);\n    }\n  }\n  connectedCallback() {\n    super.connectedCallback();\n    this.addEventListener(\"change\", __privateMethod(this, _onChange, onChange_fn));\n  }\n  disconnectedCallback() {\n    super.disconnectedCallback();\n    this.removeEventListener(\"change\", __privateMethod(this, _onChange, onChange_fn));\n  }\n  /**\n   * Returns the anchor element when it is a floating menu.\n   */\n  get anchorElement() {\n    if (this.anchor !== \"auto\")\n      return super.anchorElement;\n    return getMediaController(this).querySelector(\n      \"media-rendition-menu-button\"\n    );\n  }\n  get mediaRenditionList() {\n    return __privateGet(this, _renditionList);\n  }\n  set mediaRenditionList(list) {\n    __privateSet(this, _renditionList, list);\n    __privateMethod(this, _render, render_fn).call(this);\n  }\n  /**\n   * Get selected rendition id.\n   */\n  get mediaRenditionSelected() {\n    return getStringAttr(this, MediaUIAttributes.MEDIA_RENDITION_SELECTED);\n  }\n  set mediaRenditionSelected(id) {\n    setStringAttr(this, MediaUIAttributes.MEDIA_RENDITION_SELECTED, id);\n  }\n  get mediaHeight() {\n    return getNumericAttr(this, MediaUIAttributes.MEDIA_HEIGHT);\n  }\n  set mediaHeight(height) {\n    setNumericAttr(this, MediaUIAttributes.MEDIA_HEIGHT, height);\n  }\n}\n_renditionList = new WeakMap();\n_prevState = new WeakMap();\n_render = new WeakSet();\nrender_fn = function() {\n  if (__privateGet(this, _prevState).mediaRenditionList === JSON.stringify(this.mediaRenditionList) && __privateGet(this, _prevState).mediaHeight === this.mediaHeight)\n    return;\n  __privateGet(this, _prevState).mediaRenditionList = JSON.stringify(this.mediaRenditionList);\n  __privateGet(this, _prevState).mediaHeight = this.mediaHeight;\n  const renditionList = this.mediaRenditionList.sort(\n    (a, b) => b.height - a.height\n  );\n  for (const rendition of renditionList) {\n    rendition.selected = rendition.id === this.mediaRenditionSelected;\n  }\n  this.defaultSlot.textContent = \"\";\n  const isAuto = !this.mediaRenditionSelected;\n  for (const rendition of renditionList) {\n    const text = this.formatMenuItemText(\n      `${Math.min(rendition.width, rendition.height)}p`,\n      rendition\n    );\n    const item2 = createMenuItem({\n      type: \"radio\",\n      text,\n      value: `${rendition.id}`,\n      checked: rendition.selected && !isAuto\n    });\n    item2.prepend(createIndicator(this, \"checked-indicator\"));\n    this.defaultSlot.append(item2);\n  }\n  const item = createMenuItem({\n    type: \"radio\",\n    text: this.formatMenuItemText(\"Auto\"),\n    value: \"auto\",\n    checked: isAuto\n  });\n  const autoDescription = this.mediaHeight > 0 ? `Auto (${this.mediaHeight}p)` : \"Auto\";\n  item.dataset.description = autoDescription;\n  item.prepend(createIndicator(this, \"checked-indicator\"));\n  this.defaultSlot.append(item);\n};\n_onChange = new WeakSet();\nonChange_fn = function() {\n  if (this.value == null)\n    return;\n  const event = new globalThis.CustomEvent(\n    MediaUIEvents.MEDIA_RENDITION_REQUEST,\n    {\n      composed: true,\n      bubbles: true,\n      detail: this.value\n    }\n  );\n  this.dispatchEvent(event);\n};\nif (!globalThis.customElements.get(\"media-rendition-menu\")) {\n  globalThis.customElements.define(\"media-rendition-menu\", MediaRenditionMenu);\n}\nvar media_rendition_menu_default = MediaRenditionMenu;\nexport {\n  MediaRenditionMenu,\n  media_rendition_menu_default as default\n};\n", "import { MediaUIAttributes } from \"../constants.js\";\nimport { MediaChromeMenuButton } from \"./media-chrome-menu-button.js\";\nimport { globalThis, document } from \"../utils/server-safe-globals.js\";\nimport { nouns, tooltipLabels } from \"../labels/labels.js\";\nimport {\n  getStringAttr,\n  setStringAttr,\n  getMediaController,\n  getNumericAttr,\n  setNumericAttr\n} from \"../utils/element-utils.js\";\nconst renditionIcon = (\n  /*html*/\n  `<svg aria-hidden=\"true\" viewBox=\"0 0 24 24\">\n  <path d=\"M13.5 2.5h2v6h-2v-2h-11v-2h11v-2Zm4 2h4v2h-4v-2Zm-12 4h2v6h-2v-2h-3v-2h3v-2Zm4 2h12v2h-12v-2Zm1 4h2v6h-2v-2h-8v-2h8v-2Zm4 2h7v2h-7v-2Z\" />\n</svg>`\n);\nconst slotTemplate = document.createElement(\"template\");\nslotTemplate.innerHTML = /*html*/\n`\n  <style>\n    :host([aria-expanded=\"true\"]) slot[name=tooltip] {\n      display: none;\n    }\n  </style>\n  <slot name=\"icon\">${renditionIcon}</slot>\n`;\nclass MediaRenditionMenuButton extends MediaChromeMenuButton {\n  static get observedAttributes() {\n    return [\n      ...super.observedAttributes,\n      MediaUIAttributes.MEDIA_RENDITION_SELECTED,\n      MediaUIAttributes.MEDIA_RENDITION_UNAVAILABLE,\n      MediaUIAttributes.MEDIA_HEIGHT\n    ];\n  }\n  constructor() {\n    super({ slotTemplate, tooltipContent: tooltipLabels.RENDITIONS });\n  }\n  connectedCallback() {\n    super.connectedCallback();\n    this.setAttribute(\"aria-label\", nouns.QUALITY());\n  }\n  /**\n   * Returns the element with the id specified by the `invoketarget` attribute.\n   */\n  get invokeTargetElement() {\n    if (this.invokeTarget != void 0)\n      return super.invokeTargetElement;\n    return getMediaController(this).querySelector(\"media-rendition-menu\");\n  }\n  /**\n   * Get selected rendition id.\n   */\n  get mediaRenditionSelected() {\n    return getStringAttr(this, MediaUIAttributes.MEDIA_RENDITION_SELECTED);\n  }\n  set mediaRenditionSelected(id) {\n    setStringAttr(this, MediaUIAttributes.MEDIA_RENDITION_SELECTED, id);\n  }\n  get mediaHeight() {\n    return getNumericAttr(this, MediaUIAttributes.MEDIA_HEIGHT);\n  }\n  set mediaHeight(height) {\n    setNumericAttr(this, MediaUIAttributes.MEDIA_HEIGHT, height);\n  }\n}\nif (!globalThis.customElements.get(\"media-rendition-menu-button\")) {\n  globalThis.customElements.define(\n    \"media-rendition-menu-button\",\n    MediaRenditionMenuButton\n  );\n}\nvar media_rendition_menu_button_default = MediaRenditionMenuButton;\nexport {\n  MediaRenditionMenuButton,\n  media_rendition_menu_button_default as default\n};\n", "var ke=(t,a,e)=>{if(!a.has(t))throw TypeError(\"Cannot \"+e)};var u=(t,a,e)=>(ke(t,a,\"read from private field\"),e?e.call(t):a.get(t)),b=(t,a,e)=>{if(a.has(t))throw TypeError(\"Cannot add the same private member more than once\");a instanceof WeakSet?a.add(t):a.set(t,e)},R=(t,a,e,i)=>(ke(t,a,\"write to private field\"),i?i.call(t,e):a.set(t,e),e);var h=(t,a,e)=>(ke(t,a,\"access private method\"),e);var W=class{addEventListener(){}removeEventListener(){}dispatchEvent(a){return!0}};if(typeof DocumentFragment==\"undefined\"){class t extends W{}globalThis.DocumentFragment=t}var X=class extends W{},Re=class extends W{},Gt={get(t){},define(t,a,e){},getName(t){return null},upgrade(t){},whenDefined(t){return Promise.resolve(X)}},J,Oe=class{constructor(a,e={}){b(this,J,void 0);R(this,J,e==null?void 0:e.detail)}get detail(){return u(this,J)}initCustomEvent(){}};J=new WeakMap;function jt(t,a){return new X}var lt={document:{createElement:jt},DocumentFragment,customElements:Gt,CustomEvent:Oe,EventTarget:W,HTMLElement:X,HTMLVideoElement:Re},ut=typeof window==\"undefined\"||typeof globalThis.customElements==\"undefined\",p=ut?lt:globalThis,C=ut?lt.document:globalThis.document;import{MediaController as Ma}from\"media-chrome\";import{Attributes as He}from\"media-chrome/dist/media-container.js\";import{MediaUIAttributes as Ht}from\"media-chrome/dist/constants.js\";import\"media-chrome/dist/experimental/index.js\";import Sa,{MediaError as fe,Attributes as s}from\"@mux/mux-video\";import{StreamTypes as L,PlaybackTypes as ye,addTextTrack as Na,removeTextTrack as wa,CmcdTypeValues as Kt,i18n as G,parseJwt as Ke,MuxJWTAud as Ue}from\"@mux/playback-core\";import{VideoEvents as ea}from\"@mux/mux-video\";import{i18n as Qt}from\"@mux/playback-core\";import{StreamTypes as Le,parseJwt as ct}from\"@mux/playback-core\";function mt(t){let a=\"\";return Object.entries(t).forEach(([e,i])=>{i!=null&&(a+=`${le(e)}: ${i}; `)}),a?a.trim():void 0}function le(t){return t.replace(/([a-z])([A-Z])/g,\"$1-$2\").toLowerCase()}function ue(t){return t.replace(/[-_]([a-z])/g,(a,e)=>e.toUpperCase())}function T(t){if(t==null)return;let a=+t;return Number.isNaN(a)?void 0:a}function xe(t){let a=qt(t).toString();return a?\"?\"+a:\"\"}function qt(t){let a={};for(let e in t)t[e]!=null&&(a[e]=t[e]);return new URLSearchParams(a)}var _e=(t,a)=>!t||!a?!1:t.contains(a)?!0:_e(t,a.getRootNode().host);var pt=\"mux.com\",zt=()=>{try{return\"3.1.0\"}catch{}return\"UNKNOWN\"},Xt=zt(),ce=()=>Xt,bt=(t,{token:a,customDomain:e=pt,thumbnailTime:i,programTime:r}={})=>{var l;let o=a==null?i:void 0,{aud:d}=(l=ct(a))!=null?l:{};if(!(a&&d!==\"t\"))return`https://image.${e}/${t}/thumbnail.webp${xe({token:a,time:o,program_time:r})}`},ht=(t,{token:a,customDomain:e=pt,programStartTime:i,programEndTime:r}={})=>{var d;let{aud:o}=(d=ct(a))!=null?d:{};if(!(a&&o!==\"s\"))return`https://image.${e}/${t}/storyboard.vtt${xe({token:a,format:\"webp\",program_start_time:i,program_end_time:r})}`},Q=t=>{if(t){if([Le.LIVE,Le.ON_DEMAND].includes(t))return t;if(t!=null&&t.includes(\"live\"))return Le.LIVE}};var Jt={crossorigin:\"crossOrigin\",playsinline:\"playsInline\"};function gt(t){var a;return(a=Jt[t])!=null?a:ue(t)}var H,K,v,me=class{constructor(a,e){b(this,H,void 0);b(this,K,void 0);b(this,v,[]);R(this,H,a),R(this,K,e)}[Symbol.iterator](){return u(this,v).values()}get length(){return u(this,v).length}get value(){var a;return(a=u(this,v).join(\" \"))!=null?a:\"\"}set value(a){var e;a!==this.value&&(R(this,v,[]),this.add(...(e=a==null?void 0:a.split(\" \"))!=null?e:[]))}toString(){return this.value}item(a){return u(this,v)[a]}values(){return u(this,v).values()}keys(){return u(this,v).keys()}forEach(a){u(this,v).forEach(a)}add(...a){var e,i;a.forEach(r=>{this.contains(r)||u(this,v).push(r)}),!(this.value===\"\"&&!((e=u(this,H))!=null&&e.hasAttribute(`${u(this,K)}`)))&&((i=u(this,H))==null||i.setAttribute(`${u(this,K)}`,`${this.value}`))}remove(...a){var e;a.forEach(i=>{u(this,v).splice(u(this,v).indexOf(i),1)}),(e=u(this,H))==null||e.setAttribute(`${u(this,K)}`,`${this.value}`)}contains(a){return u(this,v).includes(a)}toggle(a,e){return typeof e!=\"undefined\"?e?(this.add(a),!0):(this.remove(a),!1):this.contains(a)?(this.remove(a),!1):(this.add(a),!0)}replace(a,e){this.remove(a),this.add(e)}};H=new WeakMap,K=new WeakMap,v=new WeakMap;var ft=`[mux-player ${ce()}]`;function _(...t){console.warn(ft,...t)}function E(...t){console.error(ft,...t)}function Me(t){var e;let a=(e=t.message)!=null?e:\"\";t.context&&(a+=` ${t.context}`),t.file&&(a+=` ${Qt(\"Read more: \")}\nhttps://github.com/muxinc/elements/blob/main/errors/${t.file}`),_(a)}var y={AUTOPLAY:\"autoplay\",CROSSORIGIN:\"crossorigin\",LOOP:\"loop\",MUTED:\"muted\",PLAYSINLINE:\"playsinline\",PRELOAD:\"preload\"},U={VOLUME:\"volume\",PLAYBACKRATE:\"playbackrate\",MUTED:\"muted\"},vt=Object.freeze({length:0,start(t){let a=t>>>0;if(a>=this.length)throw new DOMException(`Failed to execute 'start' on 'TimeRanges': The index provided (${a}) is greater than or equal to the maximum bound (${this.length}).`);return 0},end(t){let a=t>>>0;if(a>=this.length)throw new DOMException(`Failed to execute 'end' on 'TimeRanges': The index provided (${a}) is greater than or equal to the maximum bound (${this.length}).`);return 0}}),ta=ea.filter(t=>t!==\"error\"),aa=Object.values(y).filter(t=>![y.PLAYSINLINE].includes(t)),ia=Object.values(U),Z,Se=class extends p.HTMLElement{constructor(){super();b(this,Z,new WeakMap);let e=r=>{for(let o of r)o.type===\"childList\"&&(o.removedNodes.forEach(d=>{var l;(l=u(this,Z).get(d))==null||l.remove()}),o.addedNodes.forEach(d=>{var c;let l=d;l!=null&&l.slot||(c=this.media)==null||c.append(Tt(u(this,Z),d))}))};new MutationObserver(e).observe(this,{childList:!0,subtree:!0})}static get observedAttributes(){return[...aa,...ia]}init(){this.querySelectorAll(\":scope > :not([slot])\").forEach(e=>{var i;(i=this.media)==null||i.append(Tt(u(this,Z),e))}),ta.forEach(e=>{var i;(i=this.media)==null||i.addEventListener(e,r=>{this.dispatchEvent(new Event(r.type))})})}attributeChangedCallback(e,i,r){var o,d;switch(e){case U.MUTED:{this.media&&(this.media.muted=r!=null,this.media.defaultMuted=r!=null);return}case U.VOLUME:{let l=(o=T(r))!=null?o:1;this.media&&(this.media.volume=l);return}case U.PLAYBACKRATE:{let l=(d=T(r))!=null?d:1;this.media&&(this.media.playbackRate=l,this.media.defaultPlaybackRate=l);return}}}play(){var e,i;return(i=(e=this.media)==null?void 0:e.play())!=null?i:Promise.reject()}pause(){var e;(e=this.media)==null||e.pause()}load(){var e;(e=this.media)==null||e.load()}requestCast(e){var i;return(i=this.media)==null?void 0:i.requestCast(e)}get media(){var e;return(e=this.shadowRoot)==null?void 0:e.querySelector(\"mux-video\")}get audioTracks(){return this.media.audioTracks}get videoTracks(){return this.media.videoTracks}get audioRenditions(){return this.media.audioRenditions}get videoRenditions(){return this.media.videoRenditions}get paused(){var e,i;return(i=(e=this.media)==null?void 0:e.paused)!=null?i:!0}get duration(){var e,i;return(i=(e=this.media)==null?void 0:e.duration)!=null?i:NaN}get ended(){var e,i;return(i=(e=this.media)==null?void 0:e.ended)!=null?i:!1}get buffered(){var e,i;return(i=(e=this.media)==null?void 0:e.buffered)!=null?i:vt}get seekable(){var e,i;return(i=(e=this.media)==null?void 0:e.seekable)!=null?i:vt}get readyState(){var e,i;return(i=(e=this.media)==null?void 0:e.readyState)!=null?i:0}get videoWidth(){var e,i;return(i=(e=this.media)==null?void 0:e.videoWidth)!=null?i:0}get videoHeight(){var e,i;return(i=(e=this.media)==null?void 0:e.videoHeight)!=null?i:0}get currentSrc(){var e,i;return(i=(e=this.media)==null?void 0:e.currentSrc)!=null?i:\"\"}get currentTime(){var e,i;return(i=(e=this.media)==null?void 0:e.currentTime)!=null?i:0}set currentTime(e){this.media&&(this.media.currentTime=Number(e))}get volume(){var e,i;return(i=(e=this.media)==null?void 0:e.volume)!=null?i:1}set volume(e){this.media&&(this.media.volume=Number(e))}get playbackRate(){var e,i;return(i=(e=this.media)==null?void 0:e.playbackRate)!=null?i:1}set playbackRate(e){this.media&&(this.media.playbackRate=Number(e))}get defaultPlaybackRate(){var e;return(e=T(this.getAttribute(U.PLAYBACKRATE)))!=null?e:1}set defaultPlaybackRate(e){e!=null?this.setAttribute(U.PLAYBACKRATE,`${e}`):this.removeAttribute(U.PLAYBACKRATE)}get crossOrigin(){return ee(this,y.CROSSORIGIN)}set crossOrigin(e){this.setAttribute(y.CROSSORIGIN,`${e}`)}get autoplay(){return ee(this,y.AUTOPLAY)!=null}set autoplay(e){e?this.setAttribute(y.AUTOPLAY,typeof e==\"string\"?e:\"\"):this.removeAttribute(y.AUTOPLAY)}get loop(){return ee(this,y.LOOP)!=null}set loop(e){e?this.setAttribute(y.LOOP,\"\"):this.removeAttribute(y.LOOP)}get muted(){var e,i;return(i=(e=this.media)==null?void 0:e.muted)!=null?i:!1}set muted(e){this.media&&(this.media.muted=!!e)}get defaultMuted(){return ee(this,y.MUTED)!=null}set defaultMuted(e){e?this.setAttribute(y.MUTED,\"\"):this.removeAttribute(y.MUTED)}get playsInline(){return ee(this,y.PLAYSINLINE)!=null}set playsInline(e){E(\"playsInline is set to true by default and is not currently supported as a setter.\")}get preload(){return this.media?this.media.preload:this.getAttribute(\"preload\")}set preload(e){[\"\",\"none\",\"metadata\",\"auto\"].includes(e)?this.setAttribute(y.PRELOAD,e):this.removeAttribute(y.PRELOAD)}};Z=new WeakMap;function ee(t,a){return t.media?t.media.getAttribute(a):t.getAttribute(a)}function Tt(t,a){let e=t.get(a);return e||(e=a.cloneNode(),t.set(a,e)),e}var Ne=Se;import\"media-chrome/dist/media-theme-element.js\";var Et=`:host {\n  --media-control-display: var(--controls);\n  --media-loading-indicator-display: var(--loading-indicator);\n  --media-dialog-display: var(--dialog);\n  --media-play-button-display: var(--play-button);\n  --media-live-button-display: var(--live-button);\n  --media-seek-backward-button-display: var(--seek-backward-button);\n  --media-seek-forward-button-display: var(--seek-forward-button);\n  --media-mute-button-display: var(--mute-button);\n  --media-captions-button-display: var(--captions-button);\n  --media-captions-menu-button-display: var(--captions-menu-button, var(--media-captions-button-display));\n  --media-rendition-menu-button-display: var(--rendition-menu-button);\n  --media-audio-track-menu-button-display: var(--audio-track-menu-button);\n  --media-airplay-button-display: var(--airplay-button);\n  --media-pip-button-display: var(--pip-button);\n  --media-fullscreen-button-display: var(--fullscreen-button);\n  --media-cast-button-display: var(--cast-button, var(--_cast-button-drm-display));\n  --media-playback-rate-button-display: var(--playback-rate-button);\n  --media-playback-rate-menu-button-display: var(--playback-rate-menu-button);\n  --media-volume-range-display: var(--volume-range);\n  --media-time-range-display: var(--time-range);\n  --media-time-display-display: var(--time-display);\n  --media-duration-display-display: var(--duration-display);\n  --media-title-display-display: var(--title-display);\n\n  display: inline-block;\n  width: 100%;\n  line-height: 0;\n}\n\n/* Hide custom elements that are not defined yet */\n:not(:defined) {\n  display: none;\n}\n\na {\n  color: #fff;\n  font-size: 0.9em;\n  text-decoration: underline;\n}\n\nmedia-theme {\n  width: 100%;\n  height: 100%;\n  direction: ltr;\n}\n\nmedia-poster-image {\n  width: 100%;\n  height: 100%;\n}\n\nmedia-poster-image:not([src]):not([placeholdersrc]) {\n  display: none;\n}\n\n::part(top),\n[part~='top'] {\n  --media-control-display: var(--controls, var(--top-controls));\n  --media-play-button-display: var(--play-button, var(--top-play-button));\n  --media-live-button-display: var(--live-button, var(--top-live-button));\n  --media-seek-backward-button-display: var(--seek-backward-button, var(--top-seek-backward-button));\n  --media-seek-forward-button-display: var(--seek-forward-button, var(--top-seek-forward-button));\n  --media-mute-button-display: var(--mute-button, var(--top-mute-button));\n  --media-captions-button-display: var(--captions-button, var(--top-captions-button));\n  --media-captions-menu-button-display: var(\n    --captions-menu-button,\n    var(--media-captions-button-display, var(--top-captions-menu-button))\n  );\n  --media-rendition-menu-button-display: var(--rendition-menu-button, var(--top-rendition-menu-button));\n  --media-audio-track-menu-button-display: var(--audio-track-menu-button, var(--top-audio-track-menu-button));\n  --media-airplay-button-display: var(--airplay-button, var(--top-airplay-button));\n  --media-pip-button-display: var(--pip-button, var(--top-pip-button));\n  --media-fullscreen-button-display: var(--fullscreen-button, var(--top-fullscreen-button));\n  --media-cast-button-display: var(--cast-button, var(--top-cast-button, var(--_cast-button-drm-display)));\n  --media-playback-rate-button-display: var(--playback-rate-button, var(--top-playback-rate-button));\n  --media-playback-rate-menu-button-display: var(\n    --captions-menu-button,\n    var(--media-playback-rate-button-display, var(--top-playback-rate-menu-button))\n  );\n  --media-volume-range-display: var(--volume-range, var(--top-volume-range));\n  --media-time-range-display: var(--time-range, var(--top-time-range));\n  --media-time-display-display: var(--time-display, var(--top-time-display));\n  --media-duration-display-display: var(--duration-display, var(--top-duration-display));\n  --media-title-display-display: var(--title-display, var(--top-title-display));\n}\n\n::part(center),\n[part~='center'] {\n  --media-control-display: var(--controls, var(--center-controls));\n  --media-play-button-display: var(--play-button, var(--center-play-button));\n  --media-live-button-display: var(--live-button, var(--center-live-button));\n  --media-seek-backward-button-display: var(--seek-backward-button, var(--center-seek-backward-button));\n  --media-seek-forward-button-display: var(--seek-forward-button, var(--center-seek-forward-button));\n  --media-mute-button-display: var(--mute-button, var(--center-mute-button));\n  --media-captions-button-display: var(--captions-button, var(--center-captions-button));\n  --media-captions-menu-button-display: var(\n    --captions-menu-button,\n    var(--media-captions-button-display, var(--center-captions-menu-button))\n  );\n  --media-rendition-menu-button-display: var(--rendition-menu-button, var(--center-rendition-menu-button));\n  --media-audio-track-menu-button-display: var(--audio-track-menu-button, var(--center-audio-track-menu-button));\n  --media-airplay-button-display: var(--airplay-button, var(--center-airplay-button));\n  --media-pip-button-display: var(--pip-button, var(--center-pip-button));\n  --media-fullscreen-button-display: var(--fullscreen-button, var(--center-fullscreen-button));\n  --media-cast-button-display: var(--cast-button, var(--center-cast-button, var(--_cast-button-drm-display)));\n  --media-playback-rate-button-display: var(--playback-rate-button, var(--center-playback-rate-button));\n  --media-playback-rate-menu-button-display: var(\n    --playback-rate-menu-button,\n    var(--media-playback-rate-button-display, var(--center-playback-rate-menu-button))\n  );\n  --media-volume-range-display: var(--volume-range, var(--center-volume-range));\n  --media-time-range-display: var(--time-range, var(--center-time-range));\n  --media-time-display-display: var(--time-display, var(--center-time-display));\n  --media-duration-display-display: var(--duration-display, var(--center-duration-display));\n}\n\n::part(bottom),\n[part~='bottom'] {\n  --media-control-display: var(--controls, var(--bottom-controls));\n  --media-play-button-display: var(--play-button, var(--bottom-play-button));\n  --media-live-button-display: var(--live-button, var(--bottom-live-button));\n  --media-seek-backward-button-display: var(--seek-backward-button, var(--bottom-seek-backward-button));\n  --media-seek-forward-button-display: var(--seek-forward-button, var(--bottom-seek-forward-button));\n  --media-mute-button-display: var(--mute-button, var(--bottom-mute-button));\n  --media-captions-button-display: var(--captions-button, var(--bottom-captions-button));\n  --media-captions-menu-button-display: var(\n    --captions-menu-button,\n    var(--media-captions-button-display, var(--bottom-captions-menu-button))\n  );\n  --media-rendition-menu-button-display: var(--rendition-menu-button, var(--bottom-rendition-menu-button));\n  --media-audio-track-menu-button-display: var(--audio-track-menu-button, var(--bottom-audio-track-menu-button));\n  --media-airplay-button-display: var(--airplay-button, var(--bottom-airplay-button));\n  --media-pip-button-display: var(--pip-button, var(--bottom-pip-button));\n  --media-fullscreen-button-display: var(--fullscreen-button, var(--bottom-fullscreen-button));\n  --media-cast-button-display: var(--cast-button, var(--bottom-cast-button, var(--_cast-button-drm-display)));\n  --media-playback-rate-button-display: var(--playback-rate-button, var(--bottom-playback-rate-button));\n  --media-playback-rate-menu-button-display: var(\n    --playback-rate-menu-button,\n    var(--media-playback-rate-button-display, var(--bottom-playback-rate-menu-button))\n  );\n  --media-volume-range-display: var(--volume-range, var(--bottom-volume-range));\n  --media-time-range-display: var(--time-range, var(--bottom-time-range));\n  --media-time-display-display: var(--time-display, var(--bottom-time-display));\n  --media-duration-display-display: var(--duration-display, var(--bottom-duration-display));\n  --media-title-display-display: var(--title-display, var(--bottom-title-display));\n}\n\n:host([no-tooltips]) {\n  --media-tooltip-display: none;\n}\n`;var Ct=`\n  :host {\n    z-index: 100;\n    display: var(--media-dialog-display, flex);\n    justify-content: center;\n    align-items: center;\n    width: 100%;\n    height: 100%;\n    position: absolute;\n    top: 0;\n    left: 0;\n    box-sizing: border-box;\n    color: #fff;\n    line-height: 18px;\n    font-family: Arial, sans-serif;\n    padding: var(--media-dialog-backdrop-padding, 0);\n    background: var(--media-dialog-backdrop-background,\n      linear-gradient(to bottom, rgba(20, 20, 30, 0.7) 50%, rgba(20, 20, 30, 0.9))\n    );\n    /* Needs to use !important to prevent overwrite of media-chrome */\n    transition: var(--media-dialog-transition-open, visibility .2s, opacity .2s) !important;\n    transform: var(--media-dialog-transform-open, none) !important;\n    visibility: visible !important;\n    opacity: 1 !important;\n    pointer-events: auto !important;\n  }\n\n  :host(:not([open])) {\n    /* Needs to use !important to prevent overwrite of media-chrome */\n    transition: var(--media-dialog-transition-close, visibility .1s, opacity .1s) !important;\n    transform: var(--media-dialog-transform-close, none) !important;\n    visibility: hidden !important;\n    opacity: 0 !important;\n    pointer-events: none !important;\n  }\n\n  :focus-visible {\n    box-shadow: 0 0 0 2px rgba(27, 127, 204, 0.9);\n  }\n\n  .dialog {\n    position: relative;\n    box-sizing: border-box;\n    background: var(--media-dialog-background, none);\n    padding: var(--media-dialog-padding, 10px);\n    width: min(320px, 100%);\n    word-wrap: break-word;\n    max-height: 100%;\n    overflow: auto;\n    text-align: center;\n    line-height: 1.4;\n  }\n`,kt=C.createElement(\"template\");kt.innerHTML=`\n  <style>\n    ${Ct}\n  </style>\n\n  <div class=\"dialog\">\n    <slot></slot>\n  </div>\n`;var I=class extends p.HTMLElement{constructor(){var a;super(),this.attachShadow({mode:\"open\"}),(a=this.shadowRoot)==null||a.appendChild(this.constructor.template.content.cloneNode(!0))}show(){this.setAttribute(\"open\",\"\"),this.dispatchEvent(new CustomEvent(\"open\",{composed:!0,bubbles:!0})),At(this)}close(){this.hasAttribute(\"open\")&&(this.removeAttribute(\"open\"),this.dispatchEvent(new CustomEvent(\"close\",{composed:!0,bubbles:!0})),oa(this))}attributeChangedCallback(a,e,i){a===\"open\"&&e!==i&&(i!=null?this.show():this.close())}connectedCallback(){this.hasAttribute(\"role\")||this.setAttribute(\"role\",\"dialog\"),this.hasAttribute(\"open\")&&At(this)}};I.styles=Ct,I.template=kt,I.observedAttributes=[\"open\"];function At(t){let a=new CustomEvent(\"initfocus\",{composed:!0,bubbles:!0,cancelable:!0});if(t.dispatchEvent(a),a.defaultPrevented)return;let e=t.querySelector(\"[autofocus]:not([disabled])\");!e&&t.tabIndex>=0&&(e=t),e||(e=Rt(t.shadowRoot)),t._previouslyFocusedElement=C.activeElement,C.activeElement instanceof HTMLElement&&C.activeElement.blur(),t.addEventListener(\"transitionend\",()=>{e instanceof HTMLElement&&e.focus({preventScroll:!0})},{once:!0})}function Rt(t){let e=[\"button\",\"input\",\"keygen\",\"select\",\"textarea\"].map(function(r){return r+\":not([disabled])\"});e.push('[tabindex]:not([disabled]):not([tabindex=\"\"])');let i=t==null?void 0:t.querySelector(e.join(\", \"));if(!i&&\"attachShadow\"in Element.prototype){let r=(t==null?void 0:t.querySelectorAll(\"*\"))||[];for(let o=0;o<r.length&&!(r[o].tagName&&r[o].shadowRoot&&(i=Rt(r[o].shadowRoot),i));o++);}return i}function oa(t){t._previouslyFocusedElement instanceof HTMLElement&&t._previouslyFocusedElement.focus()}p.customElements.get(\"media-dialog\")||(p.customElements.define(\"media-dialog\",I),p.MediaDialog=I);var we=I;var Ot=C.createElement(\"template\");Ot.innerHTML=`\n  <style>\n    ${we.styles}\n\n    .close {\n      background: none;\n      color: inherit;\n      border: none;\n      padding: 0;\n      font: inherit;\n      cursor: pointer;\n      outline: inherit;\n      width: 28px;\n      height: 28px;\n      position: absolute;\n      top: 1rem;\n      right: 1rem;\n    }\n  </style>\n\n  <div class=\"dialog\">\n    <slot></slot>\n  </div>\n\n  <slot name=\"close\">\n    <button class=\"close\" tabindex=\"0\">\n      <svg fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n        <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\" />\n      </svg>\n    </button>\n  </slot>\n`;var te=class extends we{constructor(){var a,e;super(),(e=(a=this.shadowRoot)==null?void 0:a.querySelector(\".close\"))==null||e.addEventListener(\"click\",()=>{this.close()})}};te.template=Ot;p.customElements.get(\"mxp-dialog\")||(p.customElements.define(\"mxp-dialog\",te),p.MxpDialog=te);import{TemplateInstance as na,ChildNodePart as be,AttrPart as he}from\"media-chrome/dist/media-theme-element.js\";var ae=new WeakMap,Ie=class t{constructor(a,e){this.element=a;this.type=e;this.element.addEventListener(this.type,this);let i=ae.get(this.element);i&&i.set(this.type,this)}set(a){if(typeof a==\"function\")this.handleEvent=a.bind(this.element);else if(typeof a==\"object\"&&typeof a.handleEvent==\"function\")this.handleEvent=a.handleEvent.bind(a);else{this.element.removeEventListener(this.type,this);let e=ae.get(this.element);e&&e.delete(this.type)}}static for(a){ae.has(a.element)||ae.set(a.element,new Map);let e=a.attributeName.slice(2),i=ae.get(a.element);return i&&i.has(e)?i.get(e):new t(a.element,e)}};function sa(t,a){return t instanceof he&&t.attributeName.startsWith(\"on\")?(Ie.for(t).set(a),t.element.removeAttributeNS(t.attributeNamespace,t.attributeName),!0):!1}function da(t,a){return a instanceof pe&&t instanceof be?(a.renderInto(t),!0):!1}function la(t,a){return a instanceof DocumentFragment&&t instanceof be?(a.childNodes.length&&t.replace(...a.childNodes),!0):!1}function ua(t,a){if(t instanceof he){let e=t.attributeNamespace,i=t.element.getAttributeNS(e,t.attributeName);return String(a)!==i&&(t.value=String(a)),!0}return t.value=String(a),!0}function ma(t,a){if(t instanceof he&&a instanceof Element){let e=t.element;return e[t.attributeName]!==a&&(t.element.removeAttributeNS(t.attributeNamespace,t.attributeName),e[t.attributeName]=a),!0}return!1}function ca(t,a){if(typeof a==\"boolean\"&&t instanceof he){let e=t.attributeNamespace,i=t.element.hasAttributeNS(e,t.attributeName);return a!==i&&(t.booleanValue=a),!0}return!1}function pa(t,a){return a===!1&&t instanceof be?(t.replace(\"\"),!0):!1}function ba(t,a){ma(t,a)||ca(t,a)||sa(t,a)||pa(t,a)||da(t,a)||la(t,a)||ua(t,a)}var Pe=new Map,xt=new WeakMap,_t=new WeakMap,pe=class{constructor(a,e,i){this.strings=a;this.values=e;this.processor=i;this.stringsKey=this.strings.join(\"\u0001\")}get template(){if(Pe.has(this.stringsKey))return Pe.get(this.stringsKey);{let a=C.createElement(\"template\"),e=this.strings.length-1;return a.innerHTML=this.strings.reduce((i,r,o)=>i+r+(o<e?`{{ ${o} }}`:\"\"),\"\"),Pe.set(this.stringsKey,a),a}}renderInto(a){var r;let e=this.template;if(xt.get(a)!==e){xt.set(a,e);let o=new na(e,this.values,this.processor);_t.set(a,o),a instanceof be?a.replace(...o.children):a.appendChild(o);return}let i=_t.get(a);(r=i==null?void 0:i.update)==null||r.call(i,this.values)}},ha={processCallback(t,a,e){var i;if(e){for(let[r,o]of a)if(r in e){let d=(i=e[r])!=null?i:\"\";ba(o,d)}}}};function S(t,...a){return new pe(t,a,ha)}function Lt(t,a){t.renderInto(a)}import{i18n as ga,StreamTypes as fa,toMuxVideoURL as Mt}from\"@mux/playback-core\";var ya=t=>{let{tokens:a}=t;return a.drm?\":host { --_cast-button-drm-display: none; }\":\"\"},St=t=>S`\n  <style>\n    ${ya(t)}\n    ${Et}\n  </style>\n  ${Aa(t)}\n`,va=t=>{let a=t.hotKeys?`${t.hotKeys}`:\"\";return Q(t.streamType)===\"live\"&&(a+=\" noarrowleft noarrowright\"),a},Ta={TOP:\"top\",CENTER:\"center\",BOTTOM:\"bottom\",LAYER:\"layer\",MEDIA_LAYER:\"media-layer\",POSTER_LAYER:\"poster-layer\",VERTICAL_LAYER:\"vertical-layer\",CENTERED_LAYER:\"centered-layer\",GESTURE_LAYER:\"gesture-layer\",CONTROLLER_LAYER:\"controller\",BUTTON:\"button\",RANGE:\"range\",DISPLAY:\"display\",CONTROL_BAR:\"control-bar\",MENU_BUTTON:\"menu-button\",LISTBOX:\"listbox\",OPTION:\"option\",POSTER:\"poster\",LIVE:\"live\",PLAY:\"play\",PRE_PLAY:\"pre-play\",SEEK_BACKWARD:\"seek-backward\",SEEK_FORWARD:\"seek-forward\",MUTE:\"mute\",CAPTIONS:\"captions\",AIRPLAY:\"airplay\",PIP:\"pip\",FULLSCREEN:\"fullscreen\",CAST:\"cast\",PLAYBACK_RATE:\"playback-rate\",VOLUME:\"volume\",TIME:\"time\",TITLE:\"title\",AUDIO_TRACK:\"audio-track\",RENDITION:\"rendition\"},Ea=Object.values(Ta).join(\", \"),Aa=t=>{var a,e,i,r,o,d,l,c,O,j,k,A,x,Y,g,de,q,z,Fe,Ye,We,Ze,Ge,je,qe,ze,Xe,Je,Qe,et,tt,at,it,rt,ot,nt,st,dt;return S`\n  <media-theme\n    template=\"${t.themeTemplate||!1}\"\n    defaultstreamtype=\"${(a=t.defaultStreamType)!=null?a:!1}\"\n    hotkeys=\"${va(t)||!1}\"\n    nohotkeys=\"${t.noHotKeys||!t.hasSrc||t.isDialogOpen||!1}\"\n    noautoseektolive=\"${!!((e=t.streamType)!=null&&e.includes(fa.LIVE))&&t.targetLiveWindow!==0}\"\n    novolumepref=\"${t.novolumepref||!1}\"\n    disabled=\"${!t.hasSrc||t.isDialogOpen}\"\n    audio=\"${(i=t.audio)!=null?i:!1}\"\n    style=\"${(r=mt({\"--media-primary-color\":t.primaryColor,\"--media-secondary-color\":t.secondaryColor,\"--media-accent-color\":t.accentColor}))!=null?r:!1}\"\n    defaultsubtitles=\"${!t.defaultHiddenCaptions}\"\n    forwardseekoffset=\"${(o=t.forwardSeekOffset)!=null?o:!1}\"\n    backwardseekoffset=\"${(d=t.backwardSeekOffset)!=null?d:!1}\"\n    playbackrates=\"${(l=t.playbackRates)!=null?l:!1}\"\n    defaultshowremainingtime=\"${(c=t.defaultShowRemainingTime)!=null?c:!1}\"\n    defaultduration=\"${(O=t.defaultDuration)!=null?O:!1}\"\n    hideduration=\"${(j=t.hideDuration)!=null?j:!1}\"\n    title=\"${(k=t.title)!=null?k:!1}\"\n    exportparts=\"${Ea}\"\n  >\n    <mux-video\n      slot=\"media\"\n      target-live-window=\"${(A=t.targetLiveWindow)!=null?A:!1}\"\n      stream-type=\"${(x=Q(t.streamType))!=null?x:!1}\"\n      crossorigin=\"${(Y=t.crossOrigin)!=null?Y:\"\"}\"\n      playsinline\n      autoplay=\"${(g=t.autoplay)!=null?g:!1}\"\n      muted=\"${(de=t.muted)!=null?de:!1}\"\n      loop=\"${(q=t.loop)!=null?q:!1}\"\n      preload=\"${(z=t.preload)!=null?z:!1}\"\n      debug=\"${(Fe=t.debug)!=null?Fe:!1}\"\n      prefer-cmcd=\"${(Ye=t.preferCmcd)!=null?Ye:!1}\"\n      disable-tracking=\"${(We=t.disableTracking)!=null?We:!1}\"\n      disable-cookies=\"${(Ze=t.disableCookies)!=null?Ze:!1}\"\n      prefer-playback=\"${(Ge=t.preferPlayback)!=null?Ge:!1}\"\n      start-time=\"${t.startTime!=null?t.startTime:!1}\"\n      beacon-collection-domain=\"${(je=t.beaconCollectionDomain)!=null?je:!1}\"\n      player-software-name=\"${(qe=t.playerSoftwareName)!=null?qe:!1}\"\n      player-software-version=\"${(ze=t.playerSoftwareVersion)!=null?ze:!1}\"\n      env-key=\"${(Xe=t.envKey)!=null?Xe:!1}\"\n      custom-domain=\"${(Je=t.customDomain)!=null?Je:!1}\"\n      src=\"${t.src?t.src:t.playbackId?Mt(t):!1}\"\n      cast-src=\"${t.src?t.src:t.playbackId?Mt(t):!1}\"\n      cast-receiver=\"${(Qe=t.castReceiver)!=null?Qe:!1}\"\n      drm-token=\"${(tt=(et=t.tokens)==null?void 0:et.drm)!=null?tt:!1}\"\n      exportparts=\"video\"\n    >\n      ${t.storyboard?S`<track label=\"thumbnails\" default kind=\"metadata\" src=\"${t.storyboard}\" />`:S``}\n    </mux-video>\n    <slot name=\"poster\" slot=\"poster\">\n      <media-poster-image\n        part=\"poster\"\n        exportparts=\"poster, img\"\n        src=\"${t.poster?t.poster:!1}\"\n        placeholdersrc=\"${(at=t.placeholder)!=null?at:!1}\"\n      ></media-poster-image>\n    </slot>\n    <mxp-dialog\n      no-auto-hide\n      open=\"${(it=t.isDialogOpen)!=null?it:!1}\"\n      onclose=\"${t.onCloseErrorDialog}\"\n      oninitfocus=\"${t.onInitFocusDialog}\"\n    >\n      ${(rt=t.dialog)!=null&&rt.title?S`<h3>${t.dialog.title}</h3>`:S``}\n      <p>\n        ${(ot=t.dialog)==null?void 0:ot.message}\n        ${(nt=t.dialog)!=null&&nt.linkUrl?S`<a\n              href=\"${t.dialog.linkUrl}\"\n              target=\"_blank\"\n              rel=\"external noopener\"\n              aria-label=\"${(st=t.dialog.linkText)!=null?st:\"\"} ${ga(\"(opens in a new window)\")}\"\n              >${(dt=t.dialog.linkText)!=null?dt:t.dialog.linkUrl}</a\n            >`:S``}\n      </p>\n    </mxp-dialog>\n  </media-theme>\n`};import{errorCategoryToTokenNameOrPrefix as Nt,i18n as f,MediaError as N,MuxErrorCategory as wt,MuxErrorCode as m}from\"@mux/playback-core\";var Pt=t=>t.charAt(0).toUpperCase()+t.slice(1),Ca=(t,a=!1)=>{var e,i;if(t.muxCode){let r=Pt((e=t.errorCategory)!=null?e:\"video\"),o=Nt((i=t.errorCategory)!=null?i:wt.VIDEO);if(t.muxCode===m.NETWORK_OFFLINE)return f(\"Your device appears to be offline\",a);if(t.muxCode===m.NETWORK_TOKEN_EXPIRED)return f(\"{category} URL has expired\",a).format({category:r});if([m.NETWORK_TOKEN_SUB_MISMATCH,m.NETWORK_TOKEN_AUD_MISMATCH,m.NETWORK_TOKEN_AUD_MISSING,m.NETWORK_TOKEN_MALFORMED].includes(t.muxCode))return f(\"{category} URL is formatted incorrectly\",a).format({category:r});if(t.muxCode===m.NETWORK_TOKEN_MISSING)return f(\"Invalid {categoryName} URL\",a).format({categoryName:o});if(t.muxCode===m.NETWORK_NOT_FOUND)return f(\"{category} does not exist\",a).format({category:r});if(t.muxCode===m.NETWORK_NOT_READY)return f(\"{category} is not currently available\",a).format({category:r})}if(t.code){if(t.code===N.MEDIA_ERR_NETWORK)return f(\"Network Error\",a);if(t.code===N.MEDIA_ERR_DECODE)return f(\"Media Error\",a);if(t.code===N.MEDIA_ERR_SRC_NOT_SUPPORTED)return f(\"Source Not Supported\",a)}return f(\"Error\",a)},ka=(t,a=!1)=>{var e,i;if(t.muxCode){let r=Pt((e=t.errorCategory)!=null?e:\"video\"),o=Nt((i=t.errorCategory)!=null?i:wt.VIDEO);return t.muxCode===m.NETWORK_OFFLINE?f(\"Check your internet connection and try reloading this video.\",a):t.muxCode===m.NETWORK_TOKEN_EXPIRED?f(\"The video\\u2019s secured {tokenNamePrefix}-token has expired.\",a).format({tokenNamePrefix:o}):t.muxCode===m.NETWORK_TOKEN_SUB_MISMATCH?f(\"The video\\u2019s playback ID does not match the one encoded in the {tokenNamePrefix}-token.\",a).format({tokenNamePrefix:o}):t.muxCode===m.NETWORK_TOKEN_MALFORMED?f(\"{category} URL is formatted incorrectly\",a).format({category:r}):[m.NETWORK_TOKEN_AUD_MISMATCH,m.NETWORK_TOKEN_AUD_MISSING].includes(t.muxCode)?f(\"The {tokenNamePrefix}-token is formatted with incorrect information.\",a).format({tokenNamePrefix:o}):[m.NETWORK_TOKEN_MISSING,m.NETWORK_INVALID_URL].includes(t.muxCode)?f(\"The video URL or {tokenNamePrefix}-token are formatted with incorrect or incomplete information.\",a).format({tokenNamePrefix:o}):t.muxCode===m.NETWORK_NOT_FOUND?\"\":t.muxCode===m.NETWORK_NOT_READY?f(\"The live stream or video file are not yet ready.\",a):t.message}return t.code&&(t.code===N.MEDIA_ERR_NETWORK||t.code===N.MEDIA_ERR_DECODE||t.code===N.MEDIA_ERR_SRC_NOT_SUPPORTED),t.message},Ra=(t,a=!1)=>{let e=Ca(t,a),i=ka(t,a);return{title:e,message:i}},Oa=t=>{if(t.muxCode){if(t.muxCode===m.NETWORK_TOKEN_EXPIRED)return\"403-expired-token.md\";if(t.muxCode===m.NETWORK_TOKEN_MALFORMED)return\"403-malformatted-token.md\";if([m.NETWORK_TOKEN_AUD_MISMATCH,m.NETWORK_TOKEN_AUD_MISSING].includes(t.muxCode))return\"403-incorrect-aud-value.md\";if(t.muxCode===m.NETWORK_TOKEN_SUB_MISMATCH)return\"403-playback-id-mismatch.md\";if(t.muxCode===m.NETWORK_TOKEN_MISSING)return\"missing-signed-tokens.md\";if(t.muxCode===m.NETWORK_NOT_FOUND)return\"404-not-found.md\";if(t.muxCode===m.NETWORK_NOT_READY)return\"412-not-playable.md\"}if(t.code){if(t.code===N.MEDIA_ERR_NETWORK)return\"\";if(t.code===N.MEDIA_ERR_DECODE)return\"media-decode-error.md\";if(t.code===N.MEDIA_ERR_SRC_NOT_SUPPORTED)return\"media-src-not-supported.md\"}return\"\"},xa=(t,a)=>{let e=Oa(t);return{message:t.message,context:t.context,file:e}};function De(t,a=!1){let e=Ra(t,a),i=xa(t,a);return{dialog:e,devlog:i}}var It=`<template id=\"media-theme-gerwig\">\n  <style>\n    @keyframes pre-play-hide {\n      0% {\n        transform: scale(1);\n        opacity: 1;\n      }\n\n      30% {\n        transform: scale(0.7);\n      }\n\n      100% {\n        transform: scale(1.5);\n        opacity: 0;\n      }\n    }\n\n    :host {\n      --_primary-color: var(--media-primary-color, #fff);\n      --_secondary-color: var(--media-secondary-color, transparent);\n      --_accent-color: var(--media-accent-color, #fa50b5);\n      --_text-color: var(--media-text-color, #000);\n\n      --media-icon-color: var(--_primary-color);\n      --media-control-background: var(--_secondary-color);\n      --media-control-hover-background: var(--_accent-color);\n      --media-time-buffered-color: rgba(255, 255, 255, 0.4);\n      --media-preview-time-text-shadow: none;\n      --media-control-height: 14px;\n      --media-control-padding: 6px;\n      --media-tooltip-container-margin: 6px;\n      --media-tooltip-distance: 18px;\n\n      color: var(--_primary-color);\n      display: inline-block;\n      width: 100%;\n      height: 100%;\n    }\n\n    :host([audio]) {\n      --_secondary-color: var(--media-secondary-color, black);\n      --media-preview-time-text-shadow: none;\n    }\n\n    :host([audio]) ::slotted([slot='media']) {\n      height: 0px;\n    }\n\n    :host([audio]) media-loading-indicator {\n      display: none;\n    }\n\n    :host([audio]) media-controller {\n      background: transparent;\n    }\n\n    :host([audio]) media-controller::part(vertical-layer) {\n      background: transparent;\n    }\n\n    :host([audio]) media-control-bar {\n      width: 100%;\n      background-color: var(--media-control-background);\n    }\n\n    /*\n     * 0.433s is the transition duration for VTT Regions.\n     * Borrowed here, so the captions don't move too fast.\n     */\n    media-controller {\n      --media-webkit-text-track-transform: translateY(0) scale(0.98);\n      --media-webkit-text-track-transition: transform 0.433s ease-out 0.3s;\n    }\n    media-controller:is([mediapaused], :not([userinactive])) {\n      --media-webkit-text-track-transform: translateY(-50px) scale(0.98);\n      --media-webkit-text-track-transition: transform 0.15s ease;\n    }\n\n    /*\n     * CSS specific to iOS devices.\n     * See: https://stackoverflow.com/questions/30102792/css-media-query-to-target-only-ios-devices/60220757#60220757\n     */\n    @supports (-webkit-touch-callout: none) {\n      /* Disable subtitle adjusting for iOS Safari */\n      media-controller[mediaisfullscreen] {\n        --media-webkit-text-track-transform: unset;\n        --media-webkit-text-track-transition: unset;\n      }\n    }\n\n    media-time-range {\n      --media-box-padding-left: 6px;\n      --media-box-padding-right: 6px;\n      --media-range-bar-color: var(--_accent-color);\n      --media-time-range-buffered-color: var(--_primary-color);\n      --media-range-track-color: transparent;\n      --media-range-track-background: rgba(255, 255, 255, 0.4);\n      --media-range-thumb-background: radial-gradient(\n        circle,\n        #000 0%,\n        #000 25%,\n        var(--_accent-color) 25%,\n        var(--_accent-color)\n      );\n      --media-range-thumb-width: 12px;\n      --media-range-thumb-height: 12px;\n      --media-range-thumb-transform: scale(0);\n      --media-range-thumb-transition: transform 0.3s;\n      --media-range-thumb-opacity: 1;\n      --media-preview-background: var(--_primary-color);\n      --media-box-arrow-background: var(--_primary-color);\n      --media-preview-thumbnail-border: 5px solid var(--_primary-color);\n      --media-preview-border-radius: 5px;\n      --media-text-color: var(--_text-color);\n      --media-control-hover-background: transparent;\n      --media-preview-chapter-text-shadow: none;\n      color: var(--_accent-color);\n      padding: 0 6px;\n    }\n\n    :host([audio]) media-time-range {\n      --media-preview-time-padding: 1.5px 6px;\n      --media-preview-box-margin: 0 0 -5px;\n    }\n\n    media-time-range:hover {\n      --media-range-thumb-transform: scale(1);\n    }\n\n    media-preview-thumbnail {\n      border-bottom-width: 0;\n    }\n\n    [part~='menu'] {\n      border-radius: 2px;\n      border: 1px solid rgba(0, 0, 0, 0.1);\n      bottom: 50px;\n      padding: 2.5px 10px;\n    }\n\n    [part~='menu']::part(indicator) {\n      fill: var(--_accent-color);\n    }\n\n    [part~='menu']::part(menu-item) {\n      box-sizing: border-box;\n      display: flex;\n      align-items: center;\n      padding: 6px 10px;\n      min-height: 34px;\n    }\n\n    [part~='menu']::part(checked) {\n      font-weight: 700;\n    }\n\n    media-captions-menu,\n    media-rendition-menu,\n    media-audio-track-menu,\n    media-playback-rate-menu {\n      position: absolute; /* ensure they don't take up space in DOM on load */\n      --media-menu-background: var(--_primary-color);\n      --media-menu-item-checked-background: transparent;\n      --media-text-color: var(--_text-color);\n      --media-menu-item-hover-background: transparent;\n      --media-menu-item-hover-outline: var(--_accent-color) solid 1px;\n    }\n\n    /* The icon is a circle so make it 16px high instead of 14px for more balance. */\n    media-audio-track-menu-button {\n      --media-control-padding: 5px;\n      --media-control-height: 16px;\n    }\n\n    media-playback-rate-menu-button {\n      --media-control-padding: 6px 3px;\n      min-width: 4.4ch;\n    }\n\n    media-playback-rate-menu {\n      --media-menu-flex-direction: row;\n      --media-menu-item-checked-background: var(--_accent-color);\n      --media-menu-item-checked-indicator-display: none;\n      margin-right: 6px;\n      padding: 0;\n      --media-menu-gap: 0.25em;\n    }\n\n    media-playback-rate-menu[part~='menu']::part(menu-item) {\n      padding: 6px 6px 6px 8px;\n    }\n\n    media-playback-rate-menu[part~='menu']::part(checked) {\n      color: #fff;\n    }\n\n    :host(:not([audio])) media-time-range {\n      /* Adding px is required here for calc() */\n      --media-range-padding: 0px;\n      background: transparent;\n      z-index: 10;\n      height: 10px;\n      bottom: -3px;\n      width: 100%;\n    }\n\n    media-control-bar :is([role='button'], [role='switch'], button) {\n      line-height: 0;\n    }\n\n    media-control-bar :is([part*='button'], [part*='range'], [part*='display']) {\n      border-radius: 3px;\n    }\n\n    .spacer {\n      flex-grow: 1;\n      background-color: var(--media-control-background, rgba(20, 20, 30, 0.7));\n    }\n\n    media-control-bar[slot~='top-chrome'] {\n      min-height: 42px;\n      pointer-events: none;\n    }\n\n    media-control-bar {\n      --gradient-steps: hsl(0 0% 0% / 0) 0%, hsl(0 0% 0% / 0.013) 8.1%, hsl(0 0% 0% / 0.049) 15.5%,\n        hsl(0 0% 0% / 0.104) 22.5%, hsl(0 0% 0% / 0.175) 29%, hsl(0 0% 0% / 0.259) 35.3%, hsl(0 0% 0% / 0.352) 41.2%,\n        hsl(0 0% 0% / 0.45) 47.1%, hsl(0 0% 0% / 0.55) 52.9%, hsl(0 0% 0% / 0.648) 58.8%, hsl(0 0% 0% / 0.741) 64.7%,\n        hsl(0 0% 0% / 0.825) 71%, hsl(0 0% 0% / 0.896) 77.5%, hsl(0 0% 0% / 0.951) 84.5%, hsl(0 0% 0% / 0.987) 91.9%,\n        hsl(0 0% 0%) 100%;\n    }\n\n    :host([title]:not([audio])) media-control-bar[slot='top-chrome']::before {\n      content: '';\n      position: absolute;\n      width: 100%;\n      padding-bottom: min(100px, 25%);\n      background: linear-gradient(to top, var(--gradient-steps));\n      opacity: 0.8;\n      pointer-events: none;\n    }\n\n    :host(:not([audio])) media-control-bar[part~='bottom']::before {\n      content: '';\n      position: absolute;\n      width: 100%;\n      bottom: 0;\n      left: 0;\n      padding-bottom: min(100px, 25%);\n      background: linear-gradient(to bottom, var(--gradient-steps));\n      opacity: 0.8;\n      z-index: 1;\n      pointer-events: none;\n    }\n\n    media-control-bar[part~='bottom'] > * {\n      z-index: 20;\n    }\n\n    media-control-bar[part~='bottom'] {\n      padding: 6px 6px;\n    }\n\n    media-control-bar[slot~='top-chrome'] > * {\n      --media-control-background: transparent;\n      --media-control-hover-background: transparent;\n      position: relative;\n    }\n\n    media-controller::part(vertical-layer) {\n      transition: background-color 1s;\n    }\n\n    media-controller:is([mediapaused], :not([userinactive]))::part(vertical-layer) {\n      background-color: var(--controls-backdrop-color, var(--controls, transparent));\n      transition: background-color 0.25s;\n    }\n\n    .center-controls {\n      --media-button-icon-width: 100%;\n      --media-button-icon-height: auto;\n      --media-tooltip-display: none;\n      pointer-events: none;\n      width: 100%;\n      display: flex;\n      flex-flow: row;\n      align-items: center;\n      justify-content: center;\n      filter: drop-shadow(0 0 2px rgb(0 0 0 / 0.25)) drop-shadow(0 0 6px rgb(0 0 0 / 0.25));\n      paint-order: stroke;\n      stroke: rgba(102, 102, 102, 1);\n      stroke-width: 0.3px;\n      text-shadow:\n        0 0 2px rgb(0 0 0 / 0.25),\n        0 0 6px rgb(0 0 0 / 0.25);\n    }\n\n    .center-controls media-play-button {\n      --media-control-background: transparent;\n      --media-control-hover-background: transparent;\n      --media-control-padding: 0;\n      width: 40px;\n    }\n\n    [breakpointsm] .center-controls media-play-button {\n      width: 90px;\n      height: 90px;\n      border-radius: 50%;\n      transition: background 0.4s;\n      padding: 24px;\n      --media-control-background: #000;\n      --media-control-hover-background: var(--_accent-color);\n    }\n\n    .center-controls media-seek-backward-button,\n    .center-controls media-seek-forward-button {\n      --media-control-background: transparent;\n      --media-control-hover-background: transparent;\n      padding: 0;\n      margin: 0 20px;\n      width: max(33px, min(8%, 40px));\n    }\n\n    [breakpointsm]:not([audio]) .center-controls.pre-playback {\n      display: grid;\n      align-items: initial;\n      justify-content: initial;\n      height: 100%;\n      overflow: hidden;\n    }\n\n    [breakpointsm]:not([audio]) .center-controls.pre-playback media-play-button {\n      place-self: var(--_pre-playback-place, center);\n      grid-area: 1 / 1;\n      margin: 16px;\n    }\n\n    /* Show and hide controls or pre-playback state */\n\n    [breakpointsm]:is([mediahasplayed], :not([mediapaused])):not([audio])\n      .center-controls.pre-playback\n      media-play-button {\n      /* Using \\`forwards\\` would lead to a laggy UI after the animation got in the end state */\n      animation: 0.3s linear pre-play-hide;\n      opacity: 0;\n      pointer-events: none;\n    }\n\n    .autoplay-unmute {\n      --media-control-hover-background: transparent;\n      width: 100%;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      filter: drop-shadow(0 0 2px rgb(0 0 0 / 0.25)) drop-shadow(0 0 6px rgb(0 0 0 / 0.25));\n    }\n\n    .autoplay-unmute-btn {\n      --media-control-height: 16px;\n      border-radius: 8px;\n      background: #000;\n      color: var(--_primary-color);\n      display: flex;\n      align-items: center;\n      padding: 8px 16px;\n      font-size: 18px;\n      font-weight: 500;\n      cursor: pointer;\n    }\n\n    .autoplay-unmute-btn:hover {\n      background: var(--_accent-color);\n    }\n\n    [breakpointsm] .autoplay-unmute-btn {\n      --media-control-height: 30px;\n      padding: 14px 24px;\n      font-size: 26px;\n    }\n\n    .autoplay-unmute-btn svg {\n      margin: 0 6px 0 0;\n    }\n\n    [breakpointsm] .autoplay-unmute-btn svg {\n      margin: 0 10px 0 0;\n    }\n\n    media-controller:not([audio]):not([mediahasplayed]) *:is(media-control-bar, media-time-range) {\n      display: none;\n    }\n\n    media-loading-indicator {\n      --media-loading-icon-width: 100%;\n      --media-button-icon-height: auto;\n      display: var(--media-control-display, var(--media-loading-indicator-display, flex));\n      pointer-events: none;\n      position: absolute;\n      width: min(15%, 150px);\n      flex-flow: row;\n      align-items: center;\n      justify-content: center;\n    }\n\n    /* Intentionally don't target the div for transition but the children\n     of the div. Prevents messing with media-chrome's autohide feature. */\n    media-loading-indicator + div * {\n      transition: opacity 0.15s;\n      opacity: 1;\n    }\n\n    media-loading-indicator[medialoading]:not([mediapaused]) ~ div > * {\n      opacity: 0;\n      transition-delay: 400ms;\n    }\n\n    media-volume-range {\n      width: min(100%, 100px);\n      --media-range-padding-left: 10px;\n      --media-range-padding-right: 10px;\n      --media-range-thumb-width: 12px;\n      --media-range-thumb-height: 12px;\n      --media-range-thumb-background: radial-gradient(\n        circle,\n        #000 0%,\n        #000 25%,\n        var(--_primary-color) 25%,\n        var(--_primary-color)\n      );\n      --media-control-hover-background: none;\n    }\n\n    media-time-display {\n      white-space: nowrap;\n    }\n\n    /* Generic style for explicitly disabled controls */\n    media-control-bar[part~='bottom'] [disabled],\n    media-control-bar[part~='bottom'] [aria-disabled='true'] {\n      opacity: 60%;\n      cursor: not-allowed;\n    }\n\n    media-text-display {\n      --media-font-size: 16px;\n      --media-control-padding: 14px;\n      font-weight: 500;\n    }\n\n    media-play-button.animated *:is(g, path) {\n      transition: all 0.3s;\n    }\n\n    media-play-button.animated[mediapaused] .pause-icon-pt1 {\n      opacity: 0;\n    }\n\n    media-play-button.animated[mediapaused] .pause-icon-pt2 {\n      transform-origin: center center;\n      transform: scaleY(0);\n    }\n\n    media-play-button.animated[mediapaused] .play-icon {\n      clip-path: inset(0 0 0 0);\n    }\n\n    media-play-button.animated:not([mediapaused]) .play-icon {\n      clip-path: inset(0 0 0 100%);\n    }\n\n    media-seek-forward-button,\n    media-seek-backward-button {\n      --media-font-weight: 400;\n    }\n\n    .mute-icon {\n      display: inline-block;\n    }\n\n    .mute-icon :is(path, g) {\n      transition: opacity 0.5s;\n    }\n\n    .muted {\n      opacity: 0;\n    }\n\n    media-mute-button[mediavolumelevel='low'] :is(.volume-medium, .volume-high),\n    media-mute-button[mediavolumelevel='medium'] :is(.volume-high) {\n      opacity: 0;\n    }\n\n    media-mute-button[mediavolumelevel='off'] .unmuted {\n      opacity: 0;\n    }\n\n    media-mute-button[mediavolumelevel='off'] .muted {\n      opacity: 1;\n    }\n\n    /**\n     * Our defaults for these buttons are to hide them at small sizes\n     * users can override this with CSS\n     */\n    media-controller:not([breakpointsm]):not([audio]) {\n      --bottom-play-button: none;\n      --bottom-seek-backward-button: none;\n      --bottom-seek-forward-button: none;\n      --bottom-time-display: none;\n      --bottom-playback-rate-menu-button: none;\n      --bottom-pip-button: none;\n    }\n  </style>\n\n  <template partial=\"TitleDisplay\">\n    <template if=\"title\">\n      <media-text-display part=\"top title display\" class=\"title-display\">{{title}}</media-text-display>\n    </template>\n  </template>\n\n  <template partial=\"PlayButton\">\n    <media-play-button\n      part=\"{{section ?? 'bottom'}} play button\"\n      disabled=\"{{disabled}}\"\n      aria-disabled=\"{{disabled}}\"\n      class=\"animated\"\n    >\n      <svg aria-hidden=\"true\" viewBox=\"0 0 18 14\" slot=\"icon\">\n        <g class=\"play-icon\">\n          <path\n            d=\"M15.5987 6.2911L3.45577 0.110898C2.83667 -0.204202 2.06287 0.189698 2.06287 0.819798V13.1802C2.06287 13.8103 2.83667 14.2042 3.45577 13.8891L15.5987 7.7089C16.2178 7.3938 16.2178 6.6061 15.5987 6.2911Z\"\n          />\n        </g>\n        <g class=\"pause-icon\">\n          <path\n            class=\"pause-icon-pt1\"\n            d=\"M5.90709 0H2.96889C2.46857 0 2.06299 0.405585 2.06299 0.9059V13.0941C2.06299 13.5944 2.46857 14 2.96889 14H5.90709C6.4074 14 6.81299 13.5944 6.81299 13.0941V0.9059C6.81299 0.405585 6.4074 0 5.90709 0Z\"\n          />\n          <path\n            class=\"pause-icon-pt2\"\n            d=\"M15.1571 0H12.2189C11.7186 0 11.313 0.405585 11.313 0.9059V13.0941C11.313 13.5944 11.7186 14 12.2189 14H15.1571C15.6574 14 16.063 13.5944 16.063 13.0941V0.9059C16.063 0.405585 15.6574 0 15.1571 0Z\"\n          />\n        </g>\n      </svg>\n    </media-play-button>\n  </template>\n\n  <template partial=\"PrePlayButton\">\n    <media-play-button\n      part=\"{{section ?? 'center'}} play button pre-play\"\n      disabled=\"{{disabled}}\"\n      aria-disabled=\"{{disabled}}\"\n    >\n      <svg aria-hidden=\"true\" viewBox=\"0 0 18 14\" slot=\"icon\" style=\"transform: translate(3px, 0)\">\n        <path\n          d=\"M15.5987 6.2911L3.45577 0.110898C2.83667 -0.204202 2.06287 0.189698 2.06287 0.819798V13.1802C2.06287 13.8103 2.83667 14.2042 3.45577 13.8891L15.5987 7.7089C16.2178 7.3938 16.2178 6.6061 15.5987 6.2911Z\"\n        />\n      </svg>\n    </media-play-button>\n  </template>\n\n  <template partial=\"SeekBackwardButton\">\n    <media-seek-backward-button\n      seekoffset=\"{{backwardseekoffset}}\"\n      part=\"{{section ?? 'bottom'}} seek-backward button\"\n      disabled=\"{{disabled}}\"\n      aria-disabled=\"{{disabled}}\"\n    >\n      <svg viewBox=\"0 0 22 14\" aria-hidden=\"true\" slot=\"icon\">\n        <path\n          d=\"M3.65 2.07888L0.0864 6.7279C-0.0288 6.87812 -0.0288 7.12188 0.0864 7.2721L3.65 11.9211C3.7792 12.0896 4 11.9703 4 11.7321V2.26787C4 2.02968 3.7792 1.9104 3.65 2.07888Z\"\n        />\n        <text transform=\"translate(6 12)\" style=\"font-size: 14px; font-family: 'ArialMT', 'Arial'\">\n          {{backwardseekoffset}}\n        </text>\n      </svg>\n    </media-seek-backward-button>\n  </template>\n\n  <template partial=\"SeekForwardButton\">\n    <media-seek-forward-button\n      seekoffset=\"{{forwardseekoffset}}\"\n      part=\"{{section ?? 'bottom'}} seek-forward button\"\n      disabled=\"{{disabled}}\"\n      aria-disabled=\"{{disabled}}\"\n    >\n      <svg viewBox=\"0 0 22 14\" aria-hidden=\"true\" slot=\"icon\">\n        <g>\n          <text transform=\"translate(-1 12)\" style=\"font-size: 14px; font-family: 'ArialMT', 'Arial'\">\n            {{forwardseekoffset}}\n          </text>\n          <path\n            d=\"M18.35 11.9211L21.9136 7.2721C22.0288 7.12188 22.0288 6.87812 21.9136 6.7279L18.35 2.07888C18.2208 1.91041 18 2.02968 18 2.26787V11.7321C18 11.9703 18.2208 12.0896 18.35 11.9211Z\"\n          />\n        </g>\n      </svg>\n    </media-seek-forward-button>\n  </template>\n\n  <template partial=\"MuteButton\">\n    <media-mute-button part=\"bottom mute button\" disabled=\"{{disabled}}\" aria-disabled=\"{{disabled}}\">\n      <svg viewBox=\"0 0 18 14\" slot=\"icon\" class=\"mute-icon\" aria-hidden=\"true\">\n        <g class=\"unmuted\">\n          <path\n            d=\"M6.76786 1.21233L3.98606 3.98924H1.19937C0.593146 3.98924 0.101743 4.51375 0.101743 5.1607V6.96412L0 6.99998L0.101743 7.03583V8.83926C0.101743 9.48633 0.593146 10.0108 1.19937 10.0108H3.98606L6.76773 12.7877C7.23561 13.2547 8 12.9007 8 12.2171V1.78301C8 1.09925 7.23574 0.745258 6.76786 1.21233Z\"\n          />\n          <path\n            class=\"volume-low\"\n            d=\"M10 3.54781C10.7452 4.55141 11.1393 5.74511 11.1393 6.99991C11.1393 8.25471 10.7453 9.44791 10 10.4515L10.7988 11.0496C11.6734 9.87201 12.1356 8.47161 12.1356 6.99991C12.1356 5.52821 11.6735 4.12731 10.7988 2.94971L10 3.54781Z\"\n          />\n          <path\n            class=\"volume-medium\"\n            d=\"M12.3778 2.40086C13.2709 3.76756 13.7428 5.35806 13.7428 7.00026C13.7428 8.64246 13.2709 10.233 12.3778 11.5992L13.2106 12.1484C14.2107 10.6185 14.739 8.83796 14.739 7.00016C14.739 5.16236 14.2107 3.38236 13.2106 1.85156L12.3778 2.40086Z\"\n          />\n          <path\n            class=\"volume-high\"\n            d=\"M15.5981 0.75L14.7478 1.2719C15.7937 2.9919 16.3468 4.9723 16.3468 7C16.3468 9.0277 15.7937 11.0082 14.7478 12.7281L15.5981 13.25C16.7398 11.3722 17.343 9.211 17.343 7C17.343 4.789 16.7398 2.6268 15.5981 0.75Z\"\n          />\n        </g>\n        <g class=\"muted\">\n          <path\n            fill-rule=\"evenodd\"\n            clip-rule=\"evenodd\"\n            d=\"M4.39976 4.98924H1.19937C1.19429 4.98924 1.17777 4.98961 1.15296 5.01609C1.1271 5.04369 1.10174 5.09245 1.10174 5.1607V8.83926C1.10174 8.90761 1.12714 8.95641 1.15299 8.984C1.17779 9.01047 1.1943 9.01084 1.19937 9.01084H4.39977L7 11.6066V2.39357L4.39976 4.98924ZM7.47434 1.92006C7.4743 1.9201 7.47439 1.92002 7.47434 1.92006V1.92006ZM6.76773 12.7877L3.98606 10.0108H1.19937C0.593146 10.0108 0.101743 9.48633 0.101743 8.83926V7.03583L0 6.99998L0.101743 6.96412V5.1607C0.101743 4.51375 0.593146 3.98924 1.19937 3.98924H3.98606L6.76786 1.21233C7.23574 0.745258 8 1.09925 8 1.78301V12.2171C8 12.9007 7.23561 13.2547 6.76773 12.7877Z\"\n          />\n          <path\n            fill-rule=\"evenodd\"\n            clip-rule=\"evenodd\"\n            d=\"M15.2677 9.30323C15.463 9.49849 15.7796 9.49849 15.9749 9.30323C16.1701 9.10796 16.1701 8.79138 15.9749 8.59612L14.2071 6.82841L15.9749 5.06066C16.1702 4.8654 16.1702 4.54882 15.9749 4.35355C15.7796 4.15829 15.4631 4.15829 15.2678 4.35355L13.5 6.1213L11.7322 4.35348C11.537 4.15822 11.2204 4.15822 11.0251 4.35348C10.8298 4.54874 10.8298 4.86532 11.0251 5.06058L12.7929 6.82841L11.0251 8.59619C10.8299 8.79146 10.8299 9.10804 11.0251 9.3033C11.2204 9.49856 11.537 9.49856 11.7323 9.3033L13.5 7.53552L15.2677 9.30323Z\"\n          />\n        </g>\n      </svg>\n    </media-mute-button>\n  </template>\n\n  <template partial=\"PipButton\">\n    <media-pip-button part=\"bottom pip button\" disabled=\"{{disabled}}\" aria-disabled=\"{{disabled}}\">\n      <svg viewBox=\"0 0 18 14\" aria-hidden=\"true\" slot=\"icon\">\n        <path\n          d=\"M15.9891 0H2.011C0.9004 0 0 0.9003 0 2.0109V11.989C0 13.0996 0.9004 14 2.011 14H15.9891C17.0997 14 18 13.0997 18 11.9891V2.0109C18 0.9003 17.0997 0 15.9891 0ZM17 11.9891C17 12.5465 16.5465 13 15.9891 13H2.011C1.4536 13 1.0001 12.5465 1.0001 11.9891V2.0109C1.0001 1.4535 1.4536 0.9999 2.011 0.9999H15.9891C16.5465 0.9999 17 1.4535 17 2.0109V11.9891Z\"\n        />\n        <path\n          d=\"M15.356 5.67822H8.19523C8.03253 5.67822 7.90063 5.81012 7.90063 5.97282V11.3836C7.90063 11.5463 8.03253 11.6782 8.19523 11.6782H15.356C15.5187 11.6782 15.6506 11.5463 15.6506 11.3836V5.97282C15.6506 5.81012 15.5187 5.67822 15.356 5.67822Z\"\n        />\n      </svg>\n    </media-pip-button>\n  </template>\n\n  <template partial=\"CaptionsMenu\">\n    <media-captions-menu-button part=\"bottom captions button\">\n      <svg aria-hidden=\"true\" viewBox=\"0 0 18 14\" slot=\"on\">\n        <path\n          d=\"M15.989 0H2.011C0.9004 0 0 0.9003 0 2.0109V11.9891C0 13.0997 0.9004 14 2.011 14H15.989C17.0997 14 18 13.0997 18 11.9891V2.0109C18 0.9003 17.0997 0 15.989 0ZM4.2292 8.7639C4.5954 9.1902 5.0935 9.4031 5.7233 9.4031C6.1852 9.4031 6.5544 9.301 6.8302 9.0969C7.1061 8.8933 7.2863 8.614 7.3702 8.26H8.4322C8.3062 8.884 8.0093 9.3733 7.5411 9.7273C7.0733 10.0813 6.4703 10.2581 5.732 10.2581C5.108 10.2581 4.5699 10.1219 4.1168 9.8489C3.6637 9.5759 3.3141 9.1946 3.0685 8.7058C2.8224 8.2165 2.6994 7.6511 2.6994 7.009C2.6994 6.3611 2.8224 5.7927 3.0685 5.3034C3.3141 4.8146 3.6637 4.4323 4.1168 4.1559C4.5699 3.88 5.108 3.7418 5.732 3.7418C6.4703 3.7418 7.0733 3.922 7.5411 4.2818C8.0094 4.6422 8.3062 5.1461 8.4322 5.794H7.3702C7.2862 5.4283 7.106 5.1368 6.8302 4.921C6.5544 4.7052 6.1852 4.5968 5.7233 4.5968C5.0934 4.5968 4.5954 4.8116 4.2292 5.2404C3.8635 5.6696 3.6804 6.259 3.6804 7.009C3.6804 7.7531 3.8635 8.3381 4.2292 8.7639ZM11.0974 8.7639C11.4636 9.1902 11.9617 9.4031 12.5915 9.4031C13.0534 9.4031 13.4226 9.301 13.6984 9.0969C13.9743 8.8933 14.1545 8.614 14.2384 8.26H15.3004C15.1744 8.884 14.8775 9.3733 14.4093 9.7273C13.9415 10.0813 13.3385 10.2581 12.6002 10.2581C11.9762 10.2581 11.4381 10.1219 10.985 9.8489C10.5319 9.5759 10.1823 9.1946 9.9367 8.7058C9.6906 8.2165 9.5676 7.6511 9.5676 7.009C9.5676 6.3611 9.6906 5.7927 9.9367 5.3034C10.1823 4.8146 10.5319 4.4323 10.985 4.1559C11.4381 3.88 11.9762 3.7418 12.6002 3.7418C13.3385 3.7418 13.9415 3.922 14.4093 4.2818C14.8776 4.6422 15.1744 5.1461 15.3004 5.794H14.2384C14.1544 5.4283 13.9742 5.1368 13.6984 4.921C13.4226 4.7052 13.0534 4.5968 12.5915 4.5968C11.9616 4.5968 11.4636 4.8116 11.0974 5.2404C10.7317 5.6696 10.5486 6.259 10.5486 7.009C10.5486 7.7531 10.7317 8.3381 11.0974 8.7639Z\"\n        />\n      </svg>\n      <svg aria-hidden=\"true\" viewBox=\"0 0 18 14\" slot=\"off\">\n        <path\n          d=\"M5.73219 10.258C5.10819 10.258 4.57009 10.1218 4.11699 9.8488C3.66389 9.5758 3.31429 9.1945 3.06869 8.7057C2.82259 8.2164 2.69958 7.651 2.69958 7.0089C2.69958 6.361 2.82259 5.7926 3.06869 5.3033C3.31429 4.8145 3.66389 4.4322 4.11699 4.1558C4.57009 3.8799 5.10819 3.7417 5.73219 3.7417C6.47049 3.7417 7.07348 3.9219 7.54128 4.2817C8.00958 4.6421 8.30638 5.146 8.43238 5.7939H7.37039C7.28639 5.4282 7.10618 5.1367 6.83039 4.9209C6.55459 4.7051 6.18538 4.5967 5.72348 4.5967C5.09358 4.5967 4.59559 4.8115 4.22939 5.2403C3.86369 5.6695 3.68058 6.2589 3.68058 7.0089C3.68058 7.753 3.86369 8.338 4.22939 8.7638C4.59559 9.1901 5.09368 9.403 5.72348 9.403C6.18538 9.403 6.55459 9.3009 6.83039 9.0968C7.10629 8.8932 7.28649 8.6139 7.37039 8.2599H8.43238C8.30638 8.8839 8.00948 9.3732 7.54128 9.7272C7.07348 10.0812 6.47049 10.258 5.73219 10.258Z\"\n        />\n        <path\n          d=\"M12.6003 10.258C11.9763 10.258 11.4382 10.1218 10.9851 9.8488C10.532 9.5758 10.1824 9.1945 9.93685 8.7057C9.69075 8.2164 9.56775 7.651 9.56775 7.0089C9.56775 6.361 9.69075 5.7926 9.93685 5.3033C10.1824 4.8145 10.532 4.4322 10.9851 4.1558C11.4382 3.8799 11.9763 3.7417 12.6003 3.7417C13.3386 3.7417 13.9416 3.9219 14.4094 4.2817C14.8777 4.6421 15.1745 5.146 15.3005 5.7939H14.2385C14.1545 5.4282 13.9743 5.1367 13.6985 4.9209C13.4227 4.7051 13.0535 4.5967 12.5916 4.5967C11.9617 4.5967 11.4637 4.8115 11.0975 5.2403C10.7318 5.6695 10.5487 6.2589 10.5487 7.0089C10.5487 7.753 10.7318 8.338 11.0975 8.7638C11.4637 9.1901 11.9618 9.403 12.5916 9.403C13.0535 9.403 13.4227 9.3009 13.6985 9.0968C13.9744 8.8932 14.1546 8.6139 14.2385 8.2599H15.3005C15.1745 8.8839 14.8776 9.3732 14.4094 9.7272C13.9416 10.0812 13.3386 10.258 12.6003 10.258Z\"\n        />\n        <path\n          d=\"M15.9891 1C16.5465 1 17 1.4535 17 2.011V11.9891C17 12.5465 16.5465 13 15.9891 13H2.0109C1.4535 13 1 12.5465 1 11.9891V2.0109C1 1.4535 1.4535 0.9999 2.0109 0.9999L15.9891 1ZM15.9891 0H2.0109C0.9003 0 0 0.9003 0 2.0109V11.9891C0 13.0997 0.9003 14 2.0109 14H15.9891C17.0997 14 18 13.0997 18 11.9891V2.0109C18 0.9003 17.0997 0 15.9891 0Z\"\n        />\n      </svg>\n    </media-captions-menu-button>\n    <media-captions-menu\n      hidden\n      anchor=\"auto\"\n      part=\"bottom captions menu\"\n      disabled=\"{{disabled}}\"\n      aria-disabled=\"{{disabled}}\"\n      exportparts=\"menu-item\"\n    >\n      <div slot=\"checked-indicator\">\n        <style>\n          .indicator {\n            position: relative;\n            top: 1px;\n            width: 0.9em;\n            height: auto;\n            fill: var(--_accent-color);\n            margin-right: 5px;\n          }\n\n          [aria-checked='false'] .indicator {\n            display: none;\n          }\n        </style>\n        <svg viewBox=\"0 0 14 18\" class=\"indicator\">\n          <path\n            d=\"M12.252 3.48c-.115.033-.301.161-.425.291-.059.063-1.407 1.815-2.995 3.894s-2.897 3.79-2.908 3.802c-.013.014-.661-.616-1.672-1.624-.908-.905-1.702-1.681-1.765-1.723-.401-.27-.783-.211-1.176.183a1.285 1.285 0 0 0-.261.342.582.582 0 0 0-.082.35c0 .165.01.205.08.35.075.153.213.296 2.182 2.271 1.156 1.159 2.17 2.159 2.253 2.222.189.143.338.196.539.194.203-.003.412-.104.618-.299.205-.193 6.7-8.693 6.804-8.903a.716.716 0 0 0 .085-.345c.01-.179.005-.203-.062-.339-.124-.252-.45-.531-.746-.639a.784.784 0 0 0-.469-.027\"\n            fill-rule=\"evenodd\"\n          />\n        </svg></div\n    ></media-captions-menu>\n  </template>\n\n  <template partial=\"AirplayButton\">\n    <media-airplay-button part=\"bottom airplay button\" disabled=\"{{disabled}}\" aria-disabled=\"{{disabled}}\">\n      <svg viewBox=\"0 0 18 14\" aria-hidden=\"true\" slot=\"icon\">\n        <path\n          d=\"M16.1383 0H1.8618C0.8335 0 0 0.8335 0 1.8617V10.1382C0 11.1664 0.8335 12 1.8618 12H3.076C3.1204 11.9433 3.1503 11.8785 3.2012 11.826L4.004 11H1.8618C1.3866 11 1 10.6134 1 10.1382V1.8617C1 1.3865 1.3866 0.9999 1.8618 0.9999H16.1383C16.6135 0.9999 17.0001 1.3865 17.0001 1.8617V10.1382C17.0001 10.6134 16.6135 11 16.1383 11H13.9961L14.7989 11.826C14.8499 11.8785 14.8798 11.9432 14.9241 12H16.1383C17.1665 12 18.0001 11.1664 18.0001 10.1382V1.8617C18 0.8335 17.1665 0 16.1383 0Z\"\n        />\n        <path\n          d=\"M9.55061 8.21903C9.39981 8.06383 9.20001 7.98633 9.00011 7.98633C8.80021 7.98633 8.60031 8.06383 8.44951 8.21903L4.09771 12.697C3.62471 13.1838 3.96961 13.9998 4.64831 13.9998H13.3518C14.0304 13.9998 14.3754 13.1838 13.9023 12.697L9.55061 8.21903Z\"\n        />\n      </svg>\n    </media-airplay-button>\n  </template>\n\n  <template partial=\"FullscreenButton\">\n    <media-fullscreen-button part=\"bottom fullscreen button\" disabled=\"{{disabled}}\" aria-disabled=\"{{disabled}}\">\n      <svg viewBox=\"0 0 18 14\" aria-hidden=\"true\" slot=\"enter\">\n        <path\n          d=\"M1.00745 4.39539L1.01445 1.98789C1.01605 1.43049 1.47085 0.978289 2.02835 0.979989L6.39375 0.992589L6.39665 -0.007411L2.03125 -0.020011C0.920646 -0.023211 0.0176463 0.874489 0.0144463 1.98509L0.00744629 4.39539H1.00745Z\"\n        />\n        <path\n          d=\"M17.0144 2.03431L17.0076 4.39541H18.0076L18.0144 2.03721C18.0176 0.926712 17.1199 0.0237125 16.0093 0.0205125L11.6439 0.0078125L11.641 1.00781L16.0064 1.02041C16.5638 1.02201 17.016 1.47681 17.0144 2.03431Z\"\n        />\n        <path\n          d=\"M16.9925 9.60498L16.9855 12.0124C16.9839 12.5698 16.5291 13.022 15.9717 13.0204L11.6063 13.0078L11.6034 14.0078L15.9688 14.0204C17.0794 14.0236 17.9823 13.1259 17.9855 12.0153L17.9925 9.60498H16.9925Z\"\n        />\n        <path\n          d=\"M0.985626 11.9661L0.992426 9.60498H-0.0074737L-0.0142737 11.9632C-0.0174737 13.0738 0.880226 13.9767 1.99083 13.98L6.35623 13.9926L6.35913 12.9926L1.99373 12.98C1.43633 12.9784 0.983926 12.5236 0.985626 11.9661Z\"\n        />\n      </svg>\n      <svg viewBox=\"0 0 18 14\" aria-hidden=\"true\" slot=\"exit\">\n        <path\n          d=\"M5.39655 -0.0200195L5.38955 2.38748C5.38795 2.94488 4.93315 3.39708 4.37565 3.39538L0.0103463 3.38278L0.00744629 4.38278L4.37285 4.39538C5.48345 4.39858 6.38635 3.50088 6.38965 2.39028L6.39665 -0.0200195H5.39655Z\"\n        />\n        <path\n          d=\"M12.6411 2.36891L12.6479 0.0078125H11.6479L11.6411 2.36601C11.6379 3.47651 12.5356 4.37951 13.6462 4.38271L18.0116 4.39531L18.0145 3.39531L13.6491 3.38271C13.0917 3.38111 12.6395 2.92641 12.6411 2.36891Z\"\n        />\n        <path\n          d=\"M12.6034 14.0204L12.6104 11.613C12.612 11.0556 13.0668 10.6034 13.6242 10.605L17.9896 10.6176L17.9925 9.61759L13.6271 9.60499C12.5165 9.60179 11.6136 10.4995 11.6104 11.6101L11.6034 14.0204H12.6034Z\"\n        />\n        <path\n          d=\"M5.359 11.6315L5.3522 13.9926H6.3522L6.359 11.6344C6.3622 10.5238 5.4645 9.62088 4.3539 9.61758L-0.0115043 9.60498L-0.0144043 10.605L4.351 10.6176C4.9084 10.6192 5.3607 11.074 5.359 11.6315Z\"\n        />\n      </svg>\n    </media-fullscreen-button>\n  </template>\n\n  <template partial=\"CastButton\">\n    <media-cast-button part=\"bottom cast button\" disabled=\"{{disabled}}\" aria-disabled=\"{{disabled}}\">\n      <svg viewBox=\"0 0 18 14\" aria-hidden=\"true\" slot=\"enter\">\n        <path\n          d=\"M16.0072 0H2.0291C0.9185 0 0.0181 0.9003 0.0181 2.011V5.5009C0.357 5.5016 0.6895 5.5275 1.0181 5.5669V2.011C1.0181 1.4536 1.4716 1 2.029 1H16.0072C16.5646 1 17.0181 1.4536 17.0181 2.011V11.9891C17.0181 12.5465 16.5646 13 16.0072 13H8.4358C8.4746 13.3286 8.4999 13.6611 8.4999 13.9999H16.0071C17.1177 13.9999 18.018 13.0996 18.018 11.989V2.011C18.0181 0.9003 17.1178 0 16.0072 0ZM0 6.4999V7.4999C3.584 7.4999 6.5 10.4159 6.5 13.9999H7.5C7.5 9.8642 4.1357 6.4999 0 6.4999ZM0 8.7499V9.7499C2.3433 9.7499 4.25 11.6566 4.25 13.9999H5.25C5.25 11.1049 2.895 8.7499 0 8.7499ZM0.0181 11V14H3.0181C3.0181 12.3431 1.675 11 0.0181 11Z\"\n        />\n      </svg>\n      <svg viewBox=\"0 0 18 14\" aria-hidden=\"true\" slot=\"exit\">\n        <path\n          d=\"M15.9891 0H2.01103C0.900434 0 3.35947e-05 0.9003 3.35947e-05 2.011V5.5009C0.338934 5.5016 0.671434 5.5275 1.00003 5.5669V2.011C1.00003 1.4536 1.45353 1 2.01093 1H15.9891C16.5465 1 17 1.4536 17 2.011V11.9891C17 12.5465 16.5465 13 15.9891 13H8.41773C8.45653 13.3286 8.48183 13.6611 8.48183 13.9999H15.989C17.0996 13.9999 17.9999 13.0996 17.9999 11.989V2.011C18 0.9003 17.0997 0 15.9891 0ZM-0.0180664 6.4999V7.4999C3.56593 7.4999 6.48193 10.4159 6.48193 13.9999H7.48193C7.48193 9.8642 4.11763 6.4999 -0.0180664 6.4999ZM-0.0180664 8.7499V9.7499C2.32523 9.7499 4.23193 11.6566 4.23193 13.9999H5.23193C5.23193 11.1049 2.87693 8.7499 -0.0180664 8.7499ZM3.35947e-05 11V14H3.00003C3.00003 12.3431 1.65693 11 3.35947e-05 11Z\"\n        />\n        <path d=\"M2.15002 5.634C5.18352 6.4207 7.57252 8.8151 8.35282 11.8499H15.8501V2.1499H2.15002V5.634Z\" />\n      </svg>\n    </media-cast-button>\n  </template>\n\n  <template partial=\"LiveButton\">\n    <media-live-button part=\"{{section ?? 'top'}} live button\" disabled=\"{{disabled}}\" aria-disabled=\"{{disabled}}\">\n      <span slot=\"text\">Live</span>\n    </media-live-button>\n  </template>\n\n  <template partial=\"PlaybackRateMenu\">\n    <media-playback-rate-menu-button part=\"bottom playback-rate button\"></media-playback-rate-menu-button>\n    <media-playback-rate-menu\n      hidden\n      anchor=\"auto\"\n      rates=\"{{playbackrates}}\"\n      exportparts=\"menu-item\"\n      part=\"bottom playback-rate menu\"\n      disabled=\"{{disabled}}\"\n      aria-disabled=\"{{disabled}}\"\n    ></media-playback-rate-menu>\n  </template>\n\n  <template partial=\"VolumeRange\">\n    <media-volume-range\n      part=\"bottom volume range\"\n      disabled=\"{{disabled}}\"\n      aria-disabled=\"{{disabled}}\"\n    ></media-volume-range>\n  </template>\n\n  <template partial=\"TimeDisplay\">\n    <media-time-display\n      remaining=\"{{defaultshowremainingtime}}\"\n      showduration=\"{{!hideduration}}\"\n      part=\"bottom time display\"\n      disabled=\"{{disabled}}\"\n      aria-disabled=\"{{disabled}}\"\n    ></media-time-display>\n  </template>\n\n  <template partial=\"TimeRange\">\n    <media-time-range part=\"bottom time range\" disabled=\"{{disabled}}\" aria-disabled=\"{{disabled}}\">\n      <media-preview-thumbnail slot=\"preview\"></media-preview-thumbnail>\n      <media-preview-chapter-display slot=\"preview\"></media-preview-chapter-display>\n      <media-preview-time-display slot=\"preview\"></media-preview-time-display>\n      <div slot=\"preview\" part=\"arrow\"></div>\n    </media-time-range>\n  </template>\n\n  <template partial=\"AudioTrackMenu\">\n    <media-audio-track-menu-button part=\"bottom audio-track button\">\n      <svg aria-hidden=\"true\" slot=\"icon\" viewBox=\"0 0 18 16\">\n        <path d=\"M9 15A7 7 0 1 1 9 1a7 7 0 0 1 0 14Zm0 1A8 8 0 1 0 9 0a8 8 0 0 0 0 16Z\" />\n        <path\n          d=\"M5.2 6.3a.5.5 0 0 1 .5.5v2.4a.5.5 0 1 1-1 0V6.8a.5.5 0 0 1 .5-.5Zm2.4-2.4a.5.5 0 0 1 .5.5v7.2a.5.5 0 0 1-1 0V4.4a.5.5 0 0 1 .5-.5ZM10 5.5a.5.5 0 0 1 .5.5v4a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5Zm2.4-.8a.5.5 0 0 1 .5.5v5.6a.5.5 0 0 1-1 0V5.2a.5.5 0 0 1 .5-.5Z\"\n        />\n      </svg>\n    </media-audio-track-menu-button>\n    <media-audio-track-menu\n      hidden\n      anchor=\"auto\"\n      part=\"bottom audio-track menu\"\n      disabled=\"{{disabled}}\"\n      aria-disabled=\"{{disabled}}\"\n      exportparts=\"menu-item\"\n    >\n      <div slot=\"checked-indicator\">\n        <style>\n          .indicator {\n            position: relative;\n            top: 1px;\n            width: 0.9em;\n            height: auto;\n            fill: var(--_accent-color);\n            margin-right: 5px;\n          }\n\n          [aria-checked='false'] .indicator {\n            display: none;\n          }\n        </style>\n        <svg viewBox=\"0 0 14 18\" class=\"indicator\">\n          <path\n            d=\"M12.252 3.48c-.115.033-.301.161-.425.291-.059.063-1.407 1.815-2.995 3.894s-2.897 3.79-2.908 3.802c-.013.014-.661-.616-1.672-1.624-.908-.905-1.702-1.681-1.765-1.723-.401-.27-.783-.211-1.176.183a1.285 1.285 0 0 0-.261.342.582.582 0 0 0-.082.35c0 .165.01.205.08.35.075.153.213.296 2.182 2.271 1.156 1.159 2.17 2.159 2.253 2.222.189.143.338.196.539.194.203-.003.412-.104.618-.299.205-.193 6.7-8.693 6.804-8.903a.716.716 0 0 0 .085-.345c.01-.179.005-.203-.062-.339-.124-.252-.45-.531-.746-.639a.784.784 0 0 0-.469-.027\"\n            fill-rule=\"evenodd\"\n          />\n        </svg>\n      </div>\n    </media-audio-track-menu>\n  </template>\n\n  <template partial=\"RenditionMenu\">\n    <media-rendition-menu-button part=\"bottom rendition button\">\n      <svg aria-hidden=\"true\" slot=\"icon\" viewBox=\"0 0 18 14\">\n        <path\n          d=\"M2.25 9a2 2 0 1 0 0-4 2 2 0 0 0 0 4ZM9 9a2 2 0 1 0 0-4 2 2 0 0 0 0 4Zm6.75 0a2 2 0 1 0 0-4 2 2 0 0 0 0 4Z\"\n        />\n      </svg>\n    </media-rendition-menu-button>\n    <media-rendition-menu\n      hidden\n      anchor=\"auto\"\n      part=\"bottom rendition menu\"\n      disabled=\"{{disabled}}\"\n      aria-disabled=\"{{disabled}}\"\n    >\n      <div slot=\"checked-indicator\">\n        <style>\n          .indicator {\n            position: relative;\n            top: 1px;\n            width: 0.9em;\n            height: auto;\n            fill: var(--_accent-color);\n            margin-right: 5px;\n          }\n\n          [aria-checked='false'] .indicator {\n            display: none;\n          }\n        </style>\n        <svg viewBox=\"0 0 14 18\" class=\"indicator\">\n          <path\n            d=\"M12.252 3.48c-.115.033-.301.161-.425.291-.059.063-1.407 1.815-2.995 3.894s-2.897 3.79-2.908 3.802c-.013.014-.661-.616-1.672-1.624-.908-.905-1.702-1.681-1.765-1.723-.401-.27-.783-.211-1.176.183a1.285 1.285 0 0 0-.261.342.582.582 0 0 0-.082.35c0 .165.01.205.08.35.075.153.213.296 2.182 2.271 1.156 1.159 2.17 2.159 2.253 2.222.189.143.338.196.539.194.203-.003.412-.104.618-.299.205-.193 6.7-8.693 6.804-8.903a.716.716 0 0 0 .085-.345c.01-.179.005-.203-.062-.339-.124-.252-.45-.531-.746-.639a.784.784 0 0 0-.469-.027\"\n            fill-rule=\"evenodd\"\n          />\n        </svg>\n      </div>\n    </media-rendition-menu>\n  </template>\n\n  <media-controller\n    part=\"controller\"\n    defaultstreamtype=\"{{defaultstreamtype ?? 'on-demand'}}\"\n    breakpoints=\"sm:470\"\n    gesturesdisabled=\"{{disabled}}\"\n    hotkeys=\"{{hotkeys}}\"\n    nohotkeys=\"{{nohotkeys}}\"\n    novolumepref=\"{{novolumepref}}\"\n    audio=\"{{audio}}\"\n    noautoseektolive=\"{{noautoseektolive}}\"\n    defaultsubtitles=\"{{defaultsubtitles}}\"\n    defaultduration=\"{{defaultduration ?? false}}\"\n    keyboardforwardseekoffset=\"{{forwardseekoffset}}\"\n    keyboardbackwardseekoffset=\"{{backwardseekoffset}}\"\n    exportparts=\"layer, media-layer, poster-layer, vertical-layer, centered-layer, gesture-layer\"\n    style=\"--_pre-playback-place:{{preplaybackplace ?? 'center'}}\"\n  >\n    <slot name=\"media\" slot=\"media\"></slot>\n    <slot name=\"poster\" slot=\"poster\"></slot>\n\n    <media-loading-indicator slot=\"centered-chrome\" noautohide></media-loading-indicator>\n\n    <template if=\"!audio\">\n      <!-- Pre-playback UI -->\n      <!-- same for both on-demand and live -->\n      <div slot=\"centered-chrome\" class=\"center-controls pre-playback\">\n        <template if=\"!breakpointsm\">{{>PlayButton section=\"center\"}}</template>\n        <template if=\"breakpointsm\">{{>PrePlayButton section=\"center\"}}</template>\n      </div>\n\n      <!-- Autoplay centered unmute button -->\n      <!--\n        todo: figure out how show this with available state variables\n        needs to show when:\n        - autoplay is enabled\n        - playback has been successful\n        - audio is muted\n        - in place / instead of the pre-plaback play button\n        - not to show again after user has interacted with this button\n          - OR user has interacted with the mute button in the control bar\n      -->\n      <!--\n        There should be a >MuteButton to the left of the \"Unmute\" text, but a templating bug\n        makes it appear even if commented out in the markup, add it back when code is un-commented\n      -->\n      <!-- <div slot=\"centered-chrome\" class=\"autoplay-unmute\">\n        <div role=\"button\" class=\"autoplay-unmute-btn\">Unmute</div>\n      </div> -->\n\n      <template if=\"streamtype == 'on-demand'\">\n        <template if=\"breakpointsm\">\n          <media-control-bar part=\"control-bar top\" slot=\"top-chrome\">{{>TitleDisplay}} </media-control-bar>\n        </template>\n        {{>TimeRange}}\n        <media-control-bar part=\"control-bar bottom\">\n          {{>PlayButton}} {{>SeekBackwardButton}} {{>SeekForwardButton}} {{>TimeDisplay}} {{>MuteButton}}\n          {{>VolumeRange}}\n          <div class=\"spacer\"></div>\n          {{>RenditionMenu}} {{>PlaybackRateMenu}} {{>AudioTrackMenu}} {{>CaptionsMenu}} {{>AirplayButton}}\n          {{>CastButton}} {{>PipButton}} {{>FullscreenButton}}\n        </media-control-bar>\n      </template>\n\n      <template if=\"streamtype == 'live'\">\n        <media-control-bar part=\"control-bar top\" slot=\"top-chrome\">\n          {{>LiveButton}}\n          <template if=\"breakpointsm\"> {{>TitleDisplay}} </template>\n        </media-control-bar>\n        <template if=\"targetlivewindow > 0\">{{>TimeRange}}</template>\n        <media-control-bar part=\"control-bar bottom\">\n          {{>PlayButton}}\n          <template if=\"targetlivewindow > 0\">{{>SeekBackwardButton}} {{>SeekForwardButton}}</template>\n          {{>MuteButton}} {{>VolumeRange}}\n          <div class=\"spacer\"></div>\n          {{>RenditionMenu}} {{>AudioTrackMenu}} {{>CaptionsMenu}} {{>AirplayButton}} {{>CastButton}} {{>PipButton}}\n          {{>FullscreenButton}}\n        </media-control-bar>\n      </template>\n    </template>\n\n    <template if=\"audio\">\n      <template if=\"streamtype == 'on-demand'\">\n        <template if=\"title\">\n          <media-control-bar part=\"control-bar top\">{{>TitleDisplay}}</media-control-bar>\n        </template>\n        <media-control-bar part=\"control-bar bottom\">\n          {{>PlayButton}}\n          <template if=\"breakpointsm\"> {{>SeekBackwardButton}} {{>SeekForwardButton}} </template>\n          {{>MuteButton}}\n          <template if=\"breakpointsm\">{{>VolumeRange}}</template>\n          {{>TimeDisplay}} {{>TimeRange}}\n          <template if=\"breakpointsm\">{{>PlaybackRateMenu}}</template>\n          {{>AirplayButton}} {{>CastButton}}\n        </media-control-bar>\n      </template>\n\n      <template if=\"streamtype == 'live'\">\n        <template if=\"title\">\n          <media-control-bar part=\"control-bar top\">{{>TitleDisplay}}</media-control-bar>\n        </template>\n        <media-control-bar part=\"control-bar bottom\">\n          {{>PlayButton}} {{>LiveButton section=\"bottom\"}} {{>MuteButton}}\n          <template if=\"breakpointsm\">\n            {{>VolumeRange}}\n            <template if=\"targetlivewindow > 0\"> {{>SeekBackwardButton}} {{>SeekForwardButton}} </template>\n          </template>\n          <template if=\"targetlivewindow > 0\"> {{>TimeDisplay}} {{>TimeRange}} </template>\n          <template if=\"!targetlivewindow\"><div class=\"spacer\"></div></template>\n          {{>AirplayButton}} {{>CastButton}}\n        </media-control-bar>\n      </template>\n    </template>\n\n    <slot></slot>\n  </media-controller>\n</template>\n`;import{MediaThemeElement as La}from\"media-chrome/dist/media-theme-element.js\";import\"media-chrome/menu\";var Ve=C.createElement(\"template\");\"innerHTML\"in Ve&&(Ve.innerHTML=It);var Dt,Vt,ge=class extends La{};ge.template=(Vt=(Dt=Ve.content)==null?void 0:Dt.children)==null?void 0:Vt[0];p.customElements.get(\"media-theme-gerwig\")||p.customElements.define(\"media-theme-gerwig\",ge);var Pa=\"gerwig\";var w={SRC:\"src\",POSTER:\"poster\"},n={STYLE:\"style\",DEFAULT_HIDDEN_CAPTIONS:\"default-hidden-captions\",PRIMARY_COLOR:\"primary-color\",SECONDARY_COLOR:\"secondary-color\",ACCENT_COLOR:\"accent-color\",FORWARD_SEEK_OFFSET:\"forward-seek-offset\",BACKWARD_SEEK_OFFSET:\"backward-seek-offset\",PLAYBACK_TOKEN:\"playback-token\",THUMBNAIL_TOKEN:\"thumbnail-token\",STORYBOARD_TOKEN:\"storyboard-token\",DRM_TOKEN:\"drm-token\",STORYBOARD_SRC:\"storyboard-src\",THUMBNAIL_TIME:\"thumbnail-time\",AUDIO:\"audio\",NOHOTKEYS:\"nohotkeys\",HOTKEYS:\"hotkeys\",PLAYBACK_RATES:\"playbackrates\",DEFAULT_SHOW_REMAINING_TIME:\"default-show-remaining-time\",DEFAULT_DURATION:\"default-duration\",TITLE:\"title\",PLACEHOLDER:\"placeholder\",THEME:\"theme\",DEFAULT_STREAM_TYPE:\"default-stream-type\",TARGET_LIVE_WINDOW:\"target-live-window\",EXTRA_SOURCE_PARAMS:\"extra-source-params\",NO_VOLUME_PREF:\"no-volume-pref\",CAST_RECEIVER:\"cast-receiver\",NO_TOOLTIPS:\"no-tooltips\"},Be=[\"audio\",\"backwardseekoffset\",\"defaultduration\",\"defaultshowremainingtime\",\"defaultsubtitles\",\"noautoseektolive\",\"disabled\",\"exportparts\",\"forwardseekoffset\",\"hideduration\",\"hotkeys\",\"nohotkeys\",\"playbackrates\",\"defaultstreamtype\",\"streamtype\",\"style\",\"targetlivewindow\",\"template\",\"title\",\"novolumepref\"];function Ia(t,a){var i;return{src:!t.playbackId&&t.src,playbackId:t.playbackId,hasSrc:!!t.playbackId||!!t.src||!!t.currentSrc,poster:t.poster,storyboard:t.storyboard,storyboardSrc:t.getAttribute(n.STORYBOARD_SRC),placeholder:t.getAttribute(\"placeholder\"),themeTemplate:Da(t),thumbnailTime:!t.tokens.thumbnail&&t.thumbnailTime,autoplay:t.autoplay,crossOrigin:t.crossOrigin,loop:t.loop,noHotKeys:t.hasAttribute(n.NOHOTKEYS),hotKeys:t.getAttribute(n.HOTKEYS),muted:t.muted,paused:t.paused,preload:t.preload,envKey:t.envKey,preferCmcd:t.preferCmcd,debug:t.debug,disableTracking:t.disableTracking,disableCookies:t.disableCookies,tokens:t.tokens,beaconCollectionDomain:t.beaconCollectionDomain,maxResolution:t.maxResolution,minResolution:t.minResolution,programStartTime:t.programStartTime,programEndTime:t.programEndTime,assetStartTime:t.assetStartTime,assetEndTime:t.assetEndTime,renditionOrder:t.renditionOrder,metadata:t.metadata,playerSoftwareName:t.playerSoftwareName,playerSoftwareVersion:t.playerSoftwareVersion,startTime:t.startTime,preferPlayback:t.preferPlayback,audio:t.audio,defaultStreamType:t.defaultStreamType,targetLiveWindow:t.getAttribute(s.TARGET_LIVE_WINDOW),streamType:Q(t.getAttribute(s.STREAM_TYPE)),primaryColor:t.getAttribute(n.PRIMARY_COLOR),secondaryColor:t.getAttribute(n.SECONDARY_COLOR),accentColor:t.getAttribute(n.ACCENT_COLOR),forwardSeekOffset:t.forwardSeekOffset,backwardSeekOffset:t.backwardSeekOffset,defaultHiddenCaptions:t.defaultHiddenCaptions,defaultDuration:t.defaultDuration,defaultShowRemainingTime:t.defaultShowRemainingTime,hideDuration:Va(t),playbackRates:t.getAttribute(n.PLAYBACK_RATES),customDomain:(i=t.getAttribute(s.CUSTOM_DOMAIN))!=null?i:void 0,title:t.getAttribute(n.TITLE),novolumepref:t.hasAttribute(n.NO_VOLUME_PREF),castReceiver:t.castReceiver,...a,extraSourceParams:t.extraSourceParams}}function Da(t){var e,i;let a=t.theme;if(a){let r=(i=(e=t.getRootNode())==null?void 0:e.getElementById)==null?void 0:i.call(e,a);if(r&&r instanceof HTMLTemplateElement)return r;a.startsWith(\"media-theme-\")||(a=`media-theme-${a}`);let o=p.customElements.get(a);if(o!=null&&o.template)return o.template}}function Va(t){var e;let a=(e=t.mediaController)==null?void 0:e.querySelector(\"media-time-display\");return a&&getComputedStyle(a).getPropertyValue(\"--media-duration-display-display\").trim()===\"none\"}function Ut(t){let a=t.hasAttribute(n.TITLE)?{video_title:t.getAttribute(n.TITLE)}:{};return t.getAttributeNames().filter(e=>e.startsWith(\"metadata-\")).reduce((e,i)=>{let r=t.getAttribute(i);return r!==null&&(e[i.replace(/^metadata-/,\"\").replace(/-/g,\"_\")]=r),e},a)}var Ha=Object.values(s),Ka=Object.values(w),Ua=Object.values(n),Ba=ce(),$a=\"mux-player\",Bt={dialog:void 0,isDialogOpen:!1},Fa={redundant_streams:!0},re,oe,V,ne,F,M,D,ve,$t,se,$e,P,$,Te,Ft,Ee,Yt,Ae,Wt,Ce,Zt,ie=class extends Ne{constructor(){super();b(this,M);b(this,ve);b(this,se);b(this,P);b(this,Te);b(this,Ee);b(this,Ae);b(this,Ce);b(this,re,!1);b(this,oe,{});b(this,V,!0);b(this,ne,new me(this,\"hotkeys\"));b(this,F,{...Bt,onCloseErrorDialog:()=>h(this,se,$e).call(this,{dialog:void 0,isDialogOpen:!1}),onInitFocusDialog:e=>{_e(this,C.activeElement)||e.preventDefault()}});this.attachShadow({mode:\"open\"}),h(this,ve,$t).call(this),this.isConnected&&h(this,M,D).call(this)}static get observedAttributes(){var e;return[...(e=Ne.observedAttributes)!=null?e:[],...Ka,...Ha,...Ua]}get mediaTheme(){var e;return(e=this.shadowRoot)==null?void 0:e.querySelector(\"media-theme\")}get mediaController(){var e,i;return(i=(e=this.mediaTheme)==null?void 0:e.shadowRoot)==null?void 0:i.querySelector(\"media-controller\")}connectedCallback(){var i;let e=(i=this.shadowRoot)==null?void 0:i.querySelector(\"mux-video\");e&&(e.metadata=Ut(this))}attributeChangedCallback(e,i,r){switch(h(this,M,D).call(this),super.attributeChangedCallback(e,i,r),e){case n.HOTKEYS:u(this,ne).value=r;break;case n.THUMBNAIL_TIME:{r!=null&&this.tokens.thumbnail&&_(G(\"Use of thumbnail-time with thumbnail-token is currently unsupported. Ignore thumbnail-time.\"));break}case n.THUMBNAIL_TOKEN:{if(r){let d=Ke(r);if(d){let{aud:l}=d,c=Ue.THUMBNAIL;l!==c&&_(G(\"The {tokenNamePrefix}-token has an incorrect aud value: {aud}. aud value should be {expectedAud}.\").format({aud:l,expectedAud:c,tokenNamePrefix:\"thumbnail\"}))}}break}case n.STORYBOARD_TOKEN:{if(r){let d=Ke(r);if(d){let{aud:l}=d,c=Ue.STORYBOARD;l!==c&&_(G(\"The {tokenNamePrefix}-token has an incorrect aud value: {aud}. aud value should be {expectedAud}.\").format({aud:l,expectedAud:c,tokenNamePrefix:\"storyboard\"}))}}break}case n.DRM_TOKEN:{if(r){let d=Ke(r);if(d){let{aud:l}=d,c=Ue.DRM;l!==c&&_(G(\"The {tokenNamePrefix}-token has an incorrect aud value: {aud}. aud value should be {expectedAud}.\").format({aud:l,expectedAud:c,tokenNamePrefix:\"drm\"}))}}break}case s.PLAYBACK_ID:{r!=null&&r.includes(\"?token\")&&E(G(\"The specificed playback ID {playbackId} contains a token which must be provided via the playback-token attribute.\").format({playbackId:r}));break}case s.STREAM_TYPE:r&&![L.LIVE,L.ON_DEMAND,L.UNKNOWN].includes(r)?[\"ll-live\",\"live:dvr\",\"ll-live:dvr\"].includes(this.streamType)?this.targetLiveWindow=r.includes(\"dvr\")?Number.POSITIVE_INFINITY:0:Me({file:\"invalid-stream-type.md\",message:G(\"Invalid stream-type value supplied: `{streamType}`. Please provide stream-type as either: `on-demand` or `live`\").format({streamType:this.streamType})}):r===L.LIVE?this.getAttribute(n.TARGET_LIVE_WINDOW)==null&&(this.targetLiveWindow=0):this.targetLiveWindow=Number.NaN}[s.PLAYBACK_ID,w.SRC,n.PLAYBACK_TOKEN].includes(e)&&i!==r&&R(this,F,{...u(this,F),...Bt}),h(this,P,$).call(this,{[gt(e)]:r})}get preferCmcd(){var e;return(e=this.getAttribute(s.PREFER_CMCD))!=null?e:void 0}set preferCmcd(e){e!==this.preferCmcd&&(e?Kt.includes(e)?this.setAttribute(s.PREFER_CMCD,e):_(`Invalid value for preferCmcd. Must be one of ${Kt.join()}`):this.removeAttribute(s.PREFER_CMCD))}get hasPlayed(){var e,i;return(i=(e=this.mediaController)==null?void 0:e.hasAttribute(Ht.MEDIA_HAS_PLAYED))!=null?i:!1}get inLiveWindow(){var e;return(e=this.mediaController)==null?void 0:e.hasAttribute(Ht.MEDIA_TIME_IS_LIVE)}get _hls(){var e;return(e=this.media)==null?void 0:e._hls}get mux(){var e;return(e=this.media)==null?void 0:e.mux}get theme(){var e;return(e=this.getAttribute(n.THEME))!=null?e:Pa}set theme(e){this.setAttribute(n.THEME,`${e}`)}get themeProps(){let e=this.mediaTheme;if(!e)return;let i={};for(let r of e.getAttributeNames()){if(Be.includes(r))continue;let o=e.getAttribute(r);i[ue(r)]=o===\"\"?!0:o}return i}set themeProps(e){var r,o;h(this,M,D).call(this);let i={...this.themeProps,...e};for(let d in i){if(Be.includes(d))continue;let l=e==null?void 0:e[d];typeof l==\"boolean\"||l==null?(r=this.mediaTheme)==null||r.toggleAttribute(le(d),!!l):(o=this.mediaTheme)==null||o.setAttribute(le(d),l)}}get playbackId(){var e;return(e=this.getAttribute(s.PLAYBACK_ID))!=null?e:void 0}set playbackId(e){e?this.setAttribute(s.PLAYBACK_ID,e):this.removeAttribute(s.PLAYBACK_ID)}get src(){var e,i;return this.playbackId?(e=B(this,w.SRC))!=null?e:void 0:(i=this.getAttribute(w.SRC))!=null?i:void 0}set src(e){e?this.setAttribute(w.SRC,e):this.removeAttribute(w.SRC)}get poster(){var r;let e=this.getAttribute(w.POSTER);if(e!=null)return e;let{tokens:i}=this;if(i.playback&&!i.thumbnail){_(\"Missing expected thumbnail token. No poster image will be shown\");return}if(this.playbackId&&!this.audio)return bt(this.playbackId,{customDomain:this.customDomain,thumbnailTime:(r=this.thumbnailTime)!=null?r:this.startTime,programTime:this.programStartTime,token:i.thumbnail})}set poster(e){e||e===\"\"?this.setAttribute(w.POSTER,e):this.removeAttribute(w.POSTER)}get storyboardSrc(){var e;return(e=this.getAttribute(n.STORYBOARD_SRC))!=null?e:void 0}set storyboardSrc(e){e?this.setAttribute(n.STORYBOARD_SRC,e):this.removeAttribute(n.STORYBOARD_SRC)}get storyboard(){let{tokens:e}=this;if(this.storyboardSrc&&!e.storyboard)return this.storyboardSrc;if(!(this.audio||!this.playbackId||!this.streamType||[L.LIVE,L.UNKNOWN].includes(this.streamType)||e.playback&&!e.storyboard))return ht(this.playbackId,{customDomain:this.customDomain,token:e.storyboard,programStartTime:this.programStartTime,programEndTime:this.programEndTime})}get audio(){return this.hasAttribute(n.AUDIO)}set audio(e){if(!e){this.removeAttribute(n.AUDIO);return}this.setAttribute(n.AUDIO,\"\")}get hotkeys(){return u(this,ne)}get nohotkeys(){return this.hasAttribute(n.NOHOTKEYS)}set nohotkeys(e){if(!e){this.removeAttribute(n.NOHOTKEYS);return}this.setAttribute(n.NOHOTKEYS,\"\")}get thumbnailTime(){return T(this.getAttribute(n.THUMBNAIL_TIME))}set thumbnailTime(e){this.setAttribute(n.THUMBNAIL_TIME,`${e}`)}get title(){var e;return(e=this.getAttribute(n.TITLE))!=null?e:\"\"}set title(e){e!==this.title&&(e?this.setAttribute(n.TITLE,e):this.removeAttribute(\"title\"),super.title=e)}get placeholder(){var e;return(e=B(this,n.PLACEHOLDER))!=null?e:\"\"}set placeholder(e){this.setAttribute(n.PLACEHOLDER,`${e}`)}get primaryColor(){var i,r;let e=this.getAttribute(n.PRIMARY_COLOR);if(e!=null||this.mediaTheme&&(e=(r=(i=p.getComputedStyle(this.mediaTheme))==null?void 0:i.getPropertyValue(\"--_primary-color\"))==null?void 0:r.trim(),e))return e}set primaryColor(e){this.setAttribute(n.PRIMARY_COLOR,`${e}`)}get secondaryColor(){var i,r;let e=this.getAttribute(n.SECONDARY_COLOR);if(e!=null||this.mediaTheme&&(e=(r=(i=p.getComputedStyle(this.mediaTheme))==null?void 0:i.getPropertyValue(\"--_secondary-color\"))==null?void 0:r.trim(),e))return e}set secondaryColor(e){this.setAttribute(n.SECONDARY_COLOR,`${e}`)}get accentColor(){var i,r;let e=this.getAttribute(n.ACCENT_COLOR);if(e!=null||this.mediaTheme&&(e=(r=(i=p.getComputedStyle(this.mediaTheme))==null?void 0:i.getPropertyValue(\"--_accent-color\"))==null?void 0:r.trim(),e))return e}set accentColor(e){this.setAttribute(n.ACCENT_COLOR,`${e}`)}get defaultShowRemainingTime(){return this.hasAttribute(n.DEFAULT_SHOW_REMAINING_TIME)}set defaultShowRemainingTime(e){e?this.setAttribute(n.DEFAULT_SHOW_REMAINING_TIME,\"\"):this.removeAttribute(n.DEFAULT_SHOW_REMAINING_TIME)}get playbackRates(){if(this.hasAttribute(n.PLAYBACK_RATES))return this.getAttribute(n.PLAYBACK_RATES).trim().split(/\\s*,?\\s+/).map(e=>Number(e)).filter(e=>!Number.isNaN(e)).sort((e,i)=>e-i)}set playbackRates(e){if(!e){this.removeAttribute(n.PLAYBACK_RATES);return}this.setAttribute(n.PLAYBACK_RATES,e.join(\" \"))}get forwardSeekOffset(){var e;return(e=T(this.getAttribute(n.FORWARD_SEEK_OFFSET)))!=null?e:10}set forwardSeekOffset(e){this.setAttribute(n.FORWARD_SEEK_OFFSET,`${e}`)}get backwardSeekOffset(){var e;return(e=T(this.getAttribute(n.BACKWARD_SEEK_OFFSET)))!=null?e:10}set backwardSeekOffset(e){this.setAttribute(n.BACKWARD_SEEK_OFFSET,`${e}`)}get defaultHiddenCaptions(){return this.hasAttribute(n.DEFAULT_HIDDEN_CAPTIONS)}set defaultHiddenCaptions(e){e?this.setAttribute(n.DEFAULT_HIDDEN_CAPTIONS,\"\"):this.removeAttribute(n.DEFAULT_HIDDEN_CAPTIONS)}get defaultDuration(){return T(this.getAttribute(n.DEFAULT_DURATION))}set defaultDuration(e){e==null?this.removeAttribute(n.DEFAULT_DURATION):this.setAttribute(n.DEFAULT_DURATION,`${e}`)}get playerSoftwareName(){var e;return(e=this.getAttribute(s.PLAYER_SOFTWARE_NAME))!=null?e:$a}get playerSoftwareVersion(){var e;return(e=this.getAttribute(s.PLAYER_SOFTWARE_VERSION))!=null?e:Ba}get beaconCollectionDomain(){var e;return(e=this.getAttribute(s.BEACON_COLLECTION_DOMAIN))!=null?e:void 0}set beaconCollectionDomain(e){e!==this.beaconCollectionDomain&&(e?this.setAttribute(s.BEACON_COLLECTION_DOMAIN,e):this.removeAttribute(s.BEACON_COLLECTION_DOMAIN))}get maxResolution(){var e;return(e=this.getAttribute(s.MAX_RESOLUTION))!=null?e:void 0}set maxResolution(e){e!==this.maxResolution&&(e?this.setAttribute(s.MAX_RESOLUTION,e):this.removeAttribute(s.MAX_RESOLUTION))}get minResolution(){var e;return(e=this.getAttribute(s.MIN_RESOLUTION))!=null?e:void 0}set minResolution(e){e!==this.minResolution&&(e?this.setAttribute(s.MIN_RESOLUTION,e):this.removeAttribute(s.MIN_RESOLUTION))}get renditionOrder(){var e;return(e=this.getAttribute(s.RENDITION_ORDER))!=null?e:void 0}set renditionOrder(e){e!==this.renditionOrder&&(e?this.setAttribute(s.RENDITION_ORDER,e):this.removeAttribute(s.RENDITION_ORDER))}get programStartTime(){return T(this.getAttribute(s.PROGRAM_START_TIME))}set programStartTime(e){e==null?this.removeAttribute(s.PROGRAM_START_TIME):this.setAttribute(s.PROGRAM_START_TIME,`${e}`)}get programEndTime(){return T(this.getAttribute(s.PROGRAM_END_TIME))}set programEndTime(e){e==null?this.removeAttribute(s.PROGRAM_END_TIME):this.setAttribute(s.PROGRAM_END_TIME,`${e}`)}get assetStartTime(){return T(this.getAttribute(s.ASSET_START_TIME))}set assetStartTime(e){e==null?this.removeAttribute(s.ASSET_START_TIME):this.setAttribute(s.ASSET_START_TIME,`${e}`)}get assetEndTime(){return T(this.getAttribute(s.ASSET_END_TIME))}set assetEndTime(e){e==null?this.removeAttribute(s.ASSET_END_TIME):this.setAttribute(s.ASSET_END_TIME,`${e}`)}get extraSourceParams(){return this.hasAttribute(n.EXTRA_SOURCE_PARAMS)?[...new URLSearchParams(this.getAttribute(n.EXTRA_SOURCE_PARAMS)).entries()].reduce((e,[i,r])=>(e[i]=r,e),{}):Fa}set extraSourceParams(e){e==null?this.removeAttribute(n.EXTRA_SOURCE_PARAMS):this.setAttribute(n.EXTRA_SOURCE_PARAMS,new URLSearchParams(e).toString())}get customDomain(){var e;return(e=this.getAttribute(s.CUSTOM_DOMAIN))!=null?e:void 0}set customDomain(e){e!==this.customDomain&&(e?this.setAttribute(s.CUSTOM_DOMAIN,e):this.removeAttribute(s.CUSTOM_DOMAIN))}get envKey(){var e;return(e=B(this,s.ENV_KEY))!=null?e:void 0}set envKey(e){this.setAttribute(s.ENV_KEY,`${e}`)}get noVolumePref(){return this.hasAttribute(n.NO_VOLUME_PREF)}set noVolumePref(e){e?this.setAttribute(n.NO_VOLUME_PREF,\"\"):this.removeAttribute(n.NO_VOLUME_PREF)}get debug(){return B(this,s.DEBUG)!=null}set debug(e){e?this.setAttribute(s.DEBUG,\"\"):this.removeAttribute(s.DEBUG)}get disableTracking(){return B(this,s.DISABLE_TRACKING)!=null}set disableTracking(e){this.toggleAttribute(s.DISABLE_TRACKING,!!e)}get disableCookies(){return B(this,s.DISABLE_COOKIES)!=null}set disableCookies(e){e?this.setAttribute(s.DISABLE_COOKIES,\"\"):this.removeAttribute(s.DISABLE_COOKIES)}get streamType(){var e,i,r;return(r=(i=this.getAttribute(s.STREAM_TYPE))!=null?i:(e=this.media)==null?void 0:e.streamType)!=null?r:L.UNKNOWN}set streamType(e){this.setAttribute(s.STREAM_TYPE,`${e}`)}get defaultStreamType(){var e,i,r;return(r=(i=this.getAttribute(n.DEFAULT_STREAM_TYPE))!=null?i:(e=this.mediaController)==null?void 0:e.getAttribute(n.DEFAULT_STREAM_TYPE))!=null?r:L.ON_DEMAND}set defaultStreamType(e){e?this.setAttribute(n.DEFAULT_STREAM_TYPE,e):this.removeAttribute(n.DEFAULT_STREAM_TYPE)}get targetLiveWindow(){var e,i;return this.hasAttribute(n.TARGET_LIVE_WINDOW)?+this.getAttribute(n.TARGET_LIVE_WINDOW):(i=(e=this.media)==null?void 0:e.targetLiveWindow)!=null?i:Number.NaN}set targetLiveWindow(e){e==this.targetLiveWindow||Number.isNaN(e)&&Number.isNaN(this.targetLiveWindow)||(e==null?this.removeAttribute(n.TARGET_LIVE_WINDOW):this.setAttribute(n.TARGET_LIVE_WINDOW,`${+e}`))}get liveEdgeStart(){var e;return(e=this.media)==null?void 0:e.liveEdgeStart}get startTime(){return T(B(this,s.START_TIME))}set startTime(e){this.setAttribute(s.START_TIME,`${e}`)}get preferPlayback(){let e=this.getAttribute(s.PREFER_PLAYBACK);if(e===ye.MSE||e===ye.NATIVE)return e}set preferPlayback(e){e!==this.preferPlayback&&(e===ye.MSE||e===ye.NATIVE?this.setAttribute(s.PREFER_PLAYBACK,e):this.removeAttribute(s.PREFER_PLAYBACK))}get metadata(){var e;return(e=this.media)==null?void 0:e.metadata}set metadata(e){if(h(this,M,D).call(this),!this.media){E(\"underlying media element missing when trying to set metadata. metadata will not be set.\");return}this.media.metadata={...Ut(this),...e}}get _hlsConfig(){var e;return(e=this.media)==null?void 0:e._hlsConfig}set _hlsConfig(e){if(h(this,M,D).call(this),!this.media){E(\"underlying media element missing when trying to set _hlsConfig. _hlsConfig will not be set.\");return}this.media._hlsConfig=e}async addCuePoints(e){var i;if(h(this,M,D).call(this),!this.media){E(\"underlying media element missing when trying to addCuePoints. cuePoints will not be added.\");return}return(i=this.media)==null?void 0:i.addCuePoints(e)}get activeCuePoint(){var e;return(e=this.media)==null?void 0:e.activeCuePoint}get cuePoints(){var e,i;return(i=(e=this.media)==null?void 0:e.cuePoints)!=null?i:[]}addChapters(e){var i;if(h(this,M,D).call(this),!this.media){E(\"underlying media element missing when trying to addChapters. chapters will not be added.\");return}return(i=this.media)==null?void 0:i.addChapters(e)}get activeChapter(){var e;return(e=this.media)==null?void 0:e.activeChapter}get chapters(){var e,i;return(i=(e=this.media)==null?void 0:e.chapters)!=null?i:[]}getStartDate(){var e;return(e=this.media)==null?void 0:e.getStartDate()}get currentPdt(){var e;return(e=this.media)==null?void 0:e.currentPdt}get tokens(){let e=this.getAttribute(n.PLAYBACK_TOKEN),i=this.getAttribute(n.DRM_TOKEN),r=this.getAttribute(n.THUMBNAIL_TOKEN),o=this.getAttribute(n.STORYBOARD_TOKEN);return{...u(this,oe),...e!=null?{playback:e}:{},...i!=null?{drm:i}:{},...r!=null?{thumbnail:r}:{},...o!=null?{storyboard:o}:{}}}set tokens(e){R(this,oe,e!=null?e:{})}get playbackToken(){var e;return(e=this.getAttribute(n.PLAYBACK_TOKEN))!=null?e:void 0}set playbackToken(e){this.setAttribute(n.PLAYBACK_TOKEN,`${e}`)}get drmToken(){var e;return(e=this.getAttribute(n.DRM_TOKEN))!=null?e:void 0}set drmToken(e){this.setAttribute(n.DRM_TOKEN,`${e}`)}get thumbnailToken(){var e;return(e=this.getAttribute(n.THUMBNAIL_TOKEN))!=null?e:void 0}set thumbnailToken(e){this.setAttribute(n.THUMBNAIL_TOKEN,`${e}`)}get storyboardToken(){var e;return(e=this.getAttribute(n.STORYBOARD_TOKEN))!=null?e:void 0}set storyboardToken(e){this.setAttribute(n.STORYBOARD_TOKEN,`${e}`)}addTextTrack(e,i,r,o){var l;let d=(l=this.media)==null?void 0:l.nativeEl;if(d)return Na(d,e,i,r,o)}removeTextTrack(e){var r;let i=(r=this.media)==null?void 0:r.nativeEl;if(i)return wa(i,e)}get textTracks(){var e;return(e=this.media)==null?void 0:e.textTracks}get castReceiver(){var e;return(e=this.getAttribute(n.CAST_RECEIVER))!=null?e:void 0}set castReceiver(e){e!==this.castReceiver&&(e?this.setAttribute(n.CAST_RECEIVER,e):this.removeAttribute(n.CAST_RECEIVER))}get castCustomData(){var e;return(e=this.media)==null?void 0:e.castCustomData}set castCustomData(e){if(!this.media){E(\"underlying media element missing when trying to set castCustomData. castCustomData will not be set.\");return}this.media.castCustomData=e}get noTooltips(){return this.hasAttribute(n.NO_TOOLTIPS)}set noTooltips(e){if(!e){this.removeAttribute(n.NO_TOOLTIPS);return}this.setAttribute(n.NO_TOOLTIPS,\"\")}};re=new WeakMap,oe=new WeakMap,V=new WeakMap,ne=new WeakMap,F=new WeakMap,M=new WeakSet,D=function(){var e,i,r,o;if(!u(this,re)){R(this,re,!0),h(this,P,$).call(this);try{if(customElements.upgrade(this.mediaTheme),!(this.mediaTheme instanceof p.HTMLElement))throw\"\"}catch{E(\"<media-theme> failed to upgrade!\")}try{if(customElements.upgrade(this.media),!(this.media instanceof Sa))throw\"\"}catch{E(\"<mux-video> failed to upgrade!\")}try{if(customElements.upgrade(this.mediaController),!(this.mediaController instanceof Ma))throw\"\"}catch{E(\"<media-controller> failed to upgrade!\")}this.init(),h(this,Te,Ft).call(this),h(this,Ee,Yt).call(this),h(this,Ae,Wt).call(this),R(this,V,(i=(e=this.mediaController)==null?void 0:e.hasAttribute(He.USER_INACTIVE))!=null?i:!0),h(this,Ce,Zt).call(this),(r=this.media)==null||r.addEventListener(\"streamtypechange\",()=>h(this,P,$).call(this)),(o=this.media)==null||o.addEventListener(\"loadstart\",()=>h(this,P,$).call(this))}},ve=new WeakSet,$t=function(){var e,i;try{(e=window==null?void 0:window.CSS)==null||e.registerProperty({name:\"--media-primary-color\",syntax:\"<color>\",inherits:!0}),(i=window==null?void 0:window.CSS)==null||i.registerProperty({name:\"--media-secondary-color\",syntax:\"<color>\",inherits:!0})}catch{}},se=new WeakSet,$e=function(e){Object.assign(u(this,F),e),h(this,P,$).call(this)},P=new WeakSet,$=function(e={}){Lt(St(Ia(this,{...u(this,F),...e})),this.shadowRoot)},Te=new WeakSet,Ft=function(){let e=r=>{var l,c;if(!(r!=null&&r.startsWith(\"theme-\")))return;let o=r.replace(/^theme-/,\"\");if(Be.includes(o))return;let d=this.getAttribute(r);d!=null?(l=this.mediaTheme)==null||l.setAttribute(o,d):(c=this.mediaTheme)==null||c.removeAttribute(o)};new MutationObserver(r=>{for(let{attributeName:o}of r)e(o)}).observe(this,{attributes:!0}),this.getAttributeNames().forEach(e)},Ee=new WeakSet,Yt=function(){var i;let e=r=>{let{detail:o}=r;if(o instanceof fe||(o=new fe(o.message,o.code,o.fatal)),!(o!=null&&o.fatal)){_(o),o.data&&_(`${o.name} data:`,o.data);return}let{dialog:d,devlog:l}=De(o,!1);l.message&&Me(l),E(o),o.data&&E(`${o.name} data:`,o.data),h(this,se,$e).call(this,{isDialogOpen:!0,dialog:d})};this.addEventListener(\"error\",e),this.media&&(this.media.errorTranslator=(r={})=>{var d,l,c;if(!(((d=this.media)==null?void 0:d.error)instanceof fe))return r;let{devlog:o}=De((l=this.media)==null?void 0:l.error,!1);return{player_error_code:(c=this.media)==null?void 0:c.error.code,player_error_message:o.message?String(o.message):r.player_error_message,player_error_context:o.context?String(o.context):r.player_error_context}}),(i=this.media)==null||i.addEventListener(\"error\",r=>{var d,l;let{detail:o}=r;if(!o){let{message:c,code:O}=(l=(d=this.media)==null?void 0:d.error)!=null?l:{};o=new fe(c,O)}o!=null&&o.fatal&&this.dispatchEvent(new CustomEvent(\"error\",{detail:o}))})},Ae=new WeakSet,Wt=function(){var i,r,o,d;let e=()=>h(this,P,$).call(this);(r=(i=this.media)==null?void 0:i.textTracks)==null||r.addEventListener(\"addtrack\",e),(d=(o=this.media)==null?void 0:o.textTracks)==null||d.addEventListener(\"removetrack\",e)},Ce=new WeakSet,Zt=function(){var O,j;if(!/Firefox/i.test(navigator.userAgent))return;let i,r=new WeakMap,o=()=>this.streamType===L.LIVE&&!this.secondaryColor&&this.offsetWidth>=800,d=(k,A,x=!1)=>{if(o())return;Array.from(k&&k.activeCues||[]).forEach(g=>{if(!(!g.snapToLines||g.line<-5||g.line>=0&&g.line<10))if(!A||this.paused){let de=g.text.split(`\n`).length,q=-3;this.streamType===L.LIVE&&(q=-2);let z=q-de;if(g.line===z&&!x)return;r.has(g)||r.set(g,g.line),g.line=z}else setTimeout(()=>{g.line=r.get(g)||\"auto\"},500)})},l=()=>{var k,A;d(i,(A=(k=this.mediaController)==null?void 0:k.hasAttribute(He.USER_INACTIVE))!=null?A:!1)},c=()=>{var x,Y;let A=Array.from(((Y=(x=this.mediaController)==null?void 0:x.media)==null?void 0:Y.textTracks)||[]).filter(g=>[\"subtitles\",\"captions\"].includes(g.kind)&&g.mode===\"showing\")[0];A!==i&&(i==null||i.removeEventListener(\"cuechange\",l)),i=A,i==null||i.addEventListener(\"cuechange\",l),d(i,u(this,V))};c(),(O=this.textTracks)==null||O.addEventListener(\"change\",c),(j=this.textTracks)==null||j.addEventListener(\"addtrack\",c),this.addEventListener(\"userinactivechange\",()=>{var A,x;let k=(x=(A=this.mediaController)==null?void 0:A.hasAttribute(He.USER_INACTIVE))!=null?x:!0;u(this,V)!==k&&(R(this,V,k),d(i,u(this,V)))})};function B(t,a){return t.media?t.media.getAttribute(a):t.getAttribute(a)}p.customElements.get(\"mux-player\")||(p.customElements.define(\"mux-player\",ie),p.MuxPlayerElement=ie);var Zi=ie;export{fe as MediaError,Zi as default,B as getVideoAttribute};\n"],
  "mappings": "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5D,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAC5D,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAC5D,GAAM,KAGV,SC/DF,GAAa,KAAK,IAAI,EAAG,IAAM,EAErC,OAAU,OAaD,OAAO,CACZ,EAAI,MAAQ,CACV,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,OAAQ,GACR,KAAM,GACN,OAAQ,GACR,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,GACN,KAAM,IAGR,GAAI,GACJ,IAAK,IAAK,GAAI,MACZ,AAAI,EAAI,MAAM,eAAe,IAC3B,GAAI,MAAM,GAAK,CACb,EAAE,WAAW,GACb,EAAE,WAAW,GACb,EAAE,WAAW,GACb,EAAE,WAAW,KAKnB,GAAM,GAAY,GAAI,YAAW,CAC/B,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,IACA,IACA,IACA,IACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,GACA,IACA,IACA,IACA,IACA,GACA,GACA,IACA,IACA,IACA,IACA,IACA,IAGI,EAAY,GAAI,YAAW,CAC/B,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,IACA,IACA,IACA,IACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,GACA,IACA,IACA,IACA,IACA,GACA,GACA,IACA,IACA,IACA,IACA,IACA,IAGF,EAAI,WAAa,CACf,MAAO,EACP,MAAO,GAGT,GAAM,GAAO,GAAI,YAAW,CAC1B,EACA,EAC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AClB,GAAI,GAAI,EAAO,OACT,EAAsB,GAE5B,KAAO,KACL,EAAM,GAAK,EAAI,KAAK,EAAO,IAG7B,MAAO,GAAI,IAAI,MAAM,KAAM,CAAC,EAAI,MAAM,KAAM,GAAG,UAG1C,MAAK,EAAW,EAAU,CAC/B,GAAY,EACZ,GAAM,GAAoB,KAAK,MAAM,EAAY,IAAa,IACxD,EAAoB,KAAK,MAAM,EAAY,IAAa,IACxD,EAAQ,GAAI,YAAW,CAC3B,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACC,GAAa,GAAM,IACnB,GAAa,GAAM,IACnB,GAAa,EAAK,IACnB,EAAY,IACZ,GAAqB,GACpB,GAAqB,GAAM,IAC3B,GAAqB,EAAK,IAC3B,EAAoB,IACpB,GAAqB,GACpB,GAAqB,GAAM,IAC3B,GAAqB,EAAK,IAC3B,EAAoB,IACpB,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,GACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,IACA,IACA,IACA,MAEF,MAAO,GAAI,IAAI,EAAI,MAAM,KAAM,SAG1B,MAAK,EAAO,CACjB,GAAM,GAAU,EAAM,SAAW,GAC3B,EAAQ,GAAI,YAAW,EAAI,EAAQ,QACrC,EACA,EAGJ,IAAK,EAAI,EAAG,EAAI,EAAQ,OAAQ,IAC9B,EAAQ,EAAQ,GAAG,MACnB,EAAM,EAAI,GACP,EAAM,WAAa,EACnB,EAAM,cAAgB,EACvB,EAAM,cAGV,MAAO,GAAI,IAAI,EAAI,MAAM,KAAM,SAG1B,M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AAA;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;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;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;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;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;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;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;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;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;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;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;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;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;A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",
  "names": []
}
